From 0b5041572f24a6fb19389cecbea2816e6660f013 Mon Sep 17 00:00:00 2001 From: Boernsman Date: Fri, 14 Feb 2020 17:42:46 +0500 Subject: [PATCH] added presets to browsing --- bose/devicepluginbose.cpp | 142 +++++++++++++++++++++++++++---------- bose/devicepluginbose.h | 1 + bose/devicepluginbose.json | 8 +-- bose/soundtouch.cpp | 94 ++++++++++++++++++------ bose/soundtouch.h | 4 +- 5 files changed, 182 insertions(+), 67 deletions(-) diff --git a/bose/devicepluginbose.cpp b/bose/devicepluginbose.cpp index 5ec069a6..1dbc3638 100644 --- a/bose/devicepluginbose.cpp +++ b/bose/devicepluginbose.cpp @@ -87,6 +87,7 @@ void DevicePluginBose::setupDevice(DeviceSetupInfo *info) connect(soundTouch, &SoundTouch::bassCapabilitiesReceived, this, &DevicePluginBose::onBassCapabilitiesObjectReceived); connect(soundTouch, &SoundTouch::zoneReceived, this, &DevicePluginBose::onZoneObjectReceived); connect(soundTouch, &SoundTouch::requestExecuted, this, &DevicePluginBose::onRequestExecuted); + connect(soundTouch, &SoundTouch::presetsReceived, this, &DevicePluginBose::onPresetsReceived); m_soundTouch.insert(info->device(), soundTouch); return info->finish(Device::DeviceErrorNoError); @@ -163,37 +164,37 @@ void DevicePluginBose::executeAction(DeviceActionInfo *info) if (action.actionTypeId() == soundtouchPowerActionTypeId) { //bool power = action.param(soundtouchPowerActionPowerParamTypeId).value().toBool(); - QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_POWER); //only toggling possible + QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_POWER, true); //only toggling possible m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); } else if (action.actionTypeId() == soundtouchMuteActionTypeId) { - QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_MUTE); //only toggling possible + QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_MUTE, true); //only toggling possible m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); } else if (action.actionTypeId() == soundtouchPlayActionTypeId) { - QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PLAY); + QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PLAY, true); m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); } else if (action.actionTypeId() == soundtouchPauseActionTypeId) { - QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PAUSE); + QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PAUSE, true); m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); } else if (action.actionTypeId() == soundtouchStopActionTypeId) { - QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_STOP); + QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_STOP, true); m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); } else if (action.actionTypeId() == soundtouchSkipNextActionTypeId) { - QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_NEXT_TRACK); + QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_NEXT_TRACK, true); m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); } else if (action.actionTypeId() == soundtouchSkipBackActionTypeId) { - QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PREV_TRACK); + QUuid requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PREV_TRACK, true); m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); @@ -202,9 +203,9 @@ void DevicePluginBose::executeAction(DeviceActionInfo *info) QUuid requestId; bool shuffle = action.param(soundtouchShuffleActionShuffleParamTypeId).value().toBool(); if (shuffle) { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_SHUFFLE_ON); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_SHUFFLE_ON, true); } else { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_SHUFFLE_OFF); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_SHUFFLE_OFF, true); } m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); @@ -214,11 +215,11 @@ void DevicePluginBose::executeAction(DeviceActionInfo *info) QUuid requestId; QString repeat = action.param(soundtouchRepeatActionRepeatParamTypeId).value().toString(); if (repeat == "None") { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_REPEAT_OFF); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_REPEAT_OFF, true); } else if (repeat == "One") { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_REPEAT_ONE); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_REPEAT_ONE, true); } else if (repeat == "All") { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_REPEAT_ALL); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_REPEAT_ALL, true); } m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); @@ -242,31 +243,31 @@ void DevicePluginBose::executeAction(DeviceActionInfo *info) QUuid requestId; QString status = action.param(soundtouchPlaybackStatusActionPlaybackStatusParamTypeId).value().toString(); if (status == "Playing") { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PLAY); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PLAY, true); } else if (status == "Paused") { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PAUSE); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PAUSE, true); } else if (status == "Stopped") { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_STOP); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_STOP, true); } m_pendingActions.insert(requestId, info); connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_pendingActions.remove(requestId);}); - } else if (action.actionTypeId() == soundtouchActivatePresetActionTypeId) { + } else if (action.actionTypeId() == soundtouchSavePresetActionTypeId) { QUuid requestId; - QString preset = action.param(soundtouchActivatePresetActionPresetNumberParamTypeId).value().toString(); + QString preset = action.param(soundtouchSavePresetActionPresetNumberParamTypeId).value().toString(); if (preset.contains("1")) { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_1); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_1, true); } else if (preset.contains("2")) { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_2); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_2, true); } else if (preset.contains("3")) { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_3); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_3, true); } else if (preset.contains("4")) { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_4); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_4, true); } else if (preset.contains("5")) { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_5); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_5, true); } else if (preset.contains("6")) { - requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_6); + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_6, true); } else { qCWarning(dcBose()) << "Unhandled preset number: " << preset; info->finish(Device::DeviceErrorInvalidParameter); @@ -289,9 +290,18 @@ void DevicePluginBose::browseDevice(BrowseResult *result) Device *device = result->device(); if (device->deviceClassId() == soundtouchDeviceClassId) { SoundTouch *soundTouch = m_soundTouch.value(device); - QUuid requestId = soundTouch->getSources(); - m_asyncBrowseResults.insert(requestId, result); - connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);}); + if (result->itemId() == "presets") { + QUuid requestId = soundTouch->getPresets(); + m_asyncBrowseResults.insert(requestId, result); + connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);}); + } else { + BrowserItem presetItem("presets", "Presets", true, false); + presetItem.setIcon(BrowserItem::BrowserIcon::BrowserIconFavorites); + QUuid requestId = soundTouch->getSources(); + result->addItem(presetItem); + m_asyncBrowseResults.insert(requestId, result); + connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);}); + } } } @@ -300,9 +310,18 @@ void DevicePluginBose::browserItem(BrowserItemResult *result) Device *device = result->device(); if (device->deviceClassId() == soundtouchDeviceClassId) { SoundTouch *soundTouch = m_soundTouch.value(device); - QUuid requestId = soundTouch->getSources(); - m_asyncBrowseItemResults.insert(requestId, result); - connect(result, &BrowserItemResult::aborted, this, [this, requestId]{m_asyncBrowseItemResults.remove(requestId);}); + + if (result->itemId() == "presets") { + QUuid requestId = soundTouch->getPresets(); + m_asyncBrowseItemResults.insert(requestId, result); + connect(result, &BrowserItemResult::aborted, this, [this, requestId]{m_asyncBrowseItemResults.remove(requestId);}); + } else { + BrowserItem presetItem("presets", "Presets", true, false); + presetItem.setIcon(BrowserItem::BrowserIcon::BrowserIconFavorites); + QUuid requestId = soundTouch->getSources(); + m_asyncBrowseItemResults.insert(requestId, result); + connect(result, &BrowserItemResult::aborted, this, [this, requestId]{m_asyncBrowseItemResults.remove(requestId);}); + } } } @@ -311,16 +330,40 @@ void DevicePluginBose::executeBrowserItem(BrowserActionInfo *info) Device *device = info->device(); if (device->deviceClassId() == soundtouchDeviceClassId) { SoundTouch *soundTouch = m_soundTouch.value(device); - SourcesObject sources = m_sourcesObjects.value(device); - foreach (SourceItemObject source, sources.sourceItems) { - if (source.source == info->browserAction().itemId()) { - ContentItemObject contentItem; - contentItem.source = source.source; - contentItem.sourceAccount = source.sourceAccount; - QUuid requestId = soundTouch->setSource(contentItem); - m_asyncExecuteBrowseItems.insert(requestId, info); - connect(info, &BrowserActionInfo::aborted, this, [this, requestId]{m_asyncExecuteBrowseItems.remove(requestId);}); - break; + if (info->browserAction().itemId().startsWith("presets")) { + QUuid requestId; + int number = info->browserAction().itemId().split("&").last().toInt(); + if (number == 1) { + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_1, false); + } else if (number == 2) { + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_2, false); + } else if (number == 3) { + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_3, false); + } else if (number == 4) { + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_4, false); + } else if (number == 5) { + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_5, false); + } else if (number == 6) { + requestId = soundTouch->setKey(KEY_VALUE::KEY_VALUE_PRESET_6, false); + } else { + qCWarning(dcBose()) << "Unhandled preset number: " << number; + info->finish(Device::DeviceErrorInvalidParameter); + return; + } + m_asyncExecuteBrowseItems.insert(requestId, info); + connect(info, &BrowserActionInfo::aborted, this, [this, requestId]{m_asyncExecuteBrowseItems.remove(requestId);}); + } else { + SourcesObject sources = m_sourcesObjects.value(device); + foreach (SourceItemObject source, sources.sourceItems) { + if (source.source == info->browserAction().itemId()) { + ContentItemObject contentItem; + contentItem.source = source.source; + contentItem.sourceAccount = source.sourceAccount; + QUuid requestId = soundTouch->setSource(contentItem); + m_asyncExecuteBrowseItems.insert(requestId, info); + connect(info, &BrowserActionInfo::aborted, this, [this, requestId]{m_asyncExecuteBrowseItems.remove(requestId);}); + break; + } } } } @@ -513,3 +556,24 @@ void DevicePluginBose::onZoneObjectReceived(QUuid requestId, ZoneObject zone) qDebug(dcBose()) << "-> member:" << member.deviceID; } } + +void DevicePluginBose::onPresetsReceived(QUuid requestId, QList presets) +{ + //SoundTouch *soundtouch = static_cast(sender()); + //Device *device = m_soundTouch.key(soundtouch); + + if (m_asyncBrowseResults.contains(requestId)) { + BrowseResult *result = m_asyncBrowseResults.take(requestId); + foreach (PresetObject preset, presets) { + BrowserItem item("presets&"+QString::number(preset.presetId), QString("Preset %1").arg(QString::number(preset.presetId)), false, true); + item.setDescription(preset.ContentItem.source+" "+preset.ContentItem.itemName); + item.setThumbnail(preset.ContentItem.containerArt); + result->addItem(item); + } + result->finish(Device::DeviceErrorNoError); + } + + if (m_asyncBrowseItemResults.contains(requestId)) { + //TODO + } +} diff --git a/bose/devicepluginbose.h b/bose/devicepluginbose.h index d9a480f0..46ecf37f 100644 --- a/bose/devicepluginbose.h +++ b/bose/devicepluginbose.h @@ -87,6 +87,7 @@ private slots: void onBassCapabilitiesObjectReceived(QUuid requestId, BassCapabilitiesObject bassCapabilities); void onGroupObjectReceived(QUuid requestId, GroupObject group); void onZoneObjectReceived(QUuid requestId, ZoneObject zone); + void onPresetsReceived(QUuid requestId, QList presets); }; #endif // DEVICEPLUGINBOSE_H diff --git a/bose/devicepluginbose.json b/bose/devicepluginbose.json index 19cc0b35..3337a6eb 100644 --- a/bose/devicepluginbose.json +++ b/bose/devicepluginbose.json @@ -201,12 +201,12 @@ "displayName": "Skip Next" }, { - "id": "69969904-5bb4-401d-bede-9f31fe52d16a", - "name": "activatePreset", - "displayName": "Activate preset", + "id": "6c47e736-e2e0-47d4-9b96-7f56d2342b4d", + "name": "savePreset", + "displayName": "Save preset", "paramTypes": [ { - "id": "2a69f545-41a9-4e84-9cc6-65a5a9600b7e", + "id": "04ac6e10-922d-4774-861f-060897d3a6c0", "name": "presetNumber", "displayName": "Preset number", "type": "QString", diff --git a/bose/soundtouch.cpp b/bose/soundtouch.cpp index e62eb580..a8852fa5 100644 --- a/bose/soundtouch.cpp +++ b/bose/soundtouch.cpp @@ -162,7 +162,7 @@ QUuid SoundTouch::getBassCapabilities() return requestId; } -QUuid SoundTouch::setKey(KEY_VALUE keyValue) +QUuid SoundTouch::setKey(KEY_VALUE keyValue, bool pressed) { QUuid requestId = QUuid::createUuid(); QUrl url; @@ -174,7 +174,12 @@ QUuid SoundTouch::setKey(KEY_VALUE keyValue) QXmlStreamWriter xml(&content); xml.writeStartDocument("1.0"); xml.writeStartElement("key"); - xml.writeAttribute("state", "press"); + if (pressed) { + xml.writeAttribute("state", "press"); + } else { + xml.writeAttribute("state", "release"); + } + xml.writeAttribute("sender", "Gabbo"); switch (keyValue){ case KEY_VALUE_PLAY: @@ -225,6 +230,24 @@ QUuid SoundTouch::setKey(KEY_VALUE keyValue) case KEY_VALUE_SHUFFLE_OFF: xml.writeCharacters("SHUFFLE_OFF"); break; + case KEY_VALUE_PRESET_1: + xml.writeCharacters("PRESET_1"); + break; + case KEY_VALUE_PRESET_2: + xml.writeCharacters("PRESET_2"); + break; + case KEY_VALUE_PRESET_3: + xml.writeCharacters("PRESET_3"); + break; + case KEY_VALUE_PRESET_4: + xml.writeCharacters("PRESET_4"); + break; + case KEY_VALUE_PRESET_5: + xml.writeCharacters("PRESET_5"); + break; + case KEY_VALUE_PRESET_6: + xml.writeCharacters("PRESET_6"); + break; default: qWarning(dcBose) << "key not yet implemented"; return "0"; @@ -239,7 +262,8 @@ QUuid SoundTouch::setKey(KEY_VALUE keyValue) emitRequestStatus(requestId, reply); }); - if (keyValue == KEY_VALUE_POWER) { + //Power button needs to be released immediatelly after beeing pressed + if (keyValue == KEY_VALUE_POWER && pressed) { QUrl url; url.setHost(m_ipAddress); url.setScheme("http"); @@ -262,6 +286,7 @@ QUuid SoundTouch::setKey(KEY_VALUE keyValue) return requestId; } + QUuid SoundTouch::setVolume(int volume) { QUuid requestId = QUuid::createUuid(); @@ -850,32 +875,57 @@ void SoundTouch::parseData(QUuid requestId, const QByteArray &data) } emit bassCapabilitiesReceived(requestId, bassCapabilities); } else if (xml.name() == "presets") { - PresetObject preset; - if(xml.attributes().hasAttribute("id")) { - preset.presetId = xml.attributes().value("id").toInt(); - } - if(xml.attributes().hasAttribute("createdOn")) { - preset.createdOn= xml.attributes().value("createdOn").toULong(); - } - if(xml.attributes().hasAttribute("updatedOn")) { - preset.updatedOn = xml.attributes().value("updatedOn").toULong(); - } + QList presets; + qDebug(dcBose) << "Presets"; while(xml.readNextStartElement()){ - if(xml.name() == "ContentItem"){ - if(xml.attributes().hasAttribute("source")) { - preset.ContentItem.source = xml.attributes().value("source").toString(); + if(xml.name() == "preset"){ + PresetObject preset; + if(xml.attributes().hasAttribute("id")) { + preset.presetId = xml.attributes().value("id").toInt(); } - if(xml.attributes().hasAttribute("location")) { - preset.ContentItem.location = xml.attributes().value("location").toString(); + if(xml.attributes().hasAttribute("createdOn")) { + preset.createdOn= xml.attributes().value("createdOn").toULong(); } - if(xml.attributes().hasAttribute("sourceAccount")) { - preset.ContentItem.sourceAccount = xml.attributes().value("sourceAccount").toString(); + if(xml.attributes().hasAttribute("updatedOn")) { + preset.updatedOn = xml.attributes().value("updatedOn").toULong(); } - }else { + qDebug(dcBose) << "Preset" << preset.presetId; + while(xml.readNextStartElement()){ + + if (xml.name() == "ContentItem") { + if(xml.attributes().hasAttribute("source")) { + preset.ContentItem.source = xml.attributes().value("source").toString(); + } + if(xml.attributes().hasAttribute("location")) { + preset.ContentItem.location = xml.attributes().value("location").toString(); + } + if(xml.attributes().hasAttribute("sourceAccount")) { + preset.ContentItem.sourceAccount = xml.attributes().value("sourceAccount").toString(); + } + + while(xml.readNextStartElement()){ + if (xml.name() == "itemName") { + preset.ContentItem.itemName = xml.readElementText(); + } else if (xml.name() == "containerArt"){ + preset.ContentItem.containerArt = xml.readElementText(); + } else { + qCWarning(dcBose()) << "Presets: unhandled XML element" << xml.name(); + xml.skipCurrentElement(); + } + } + + } else { + qCWarning(dcBose()) << "Presets: unhandled XML element" << xml.name(); + xml.skipCurrentElement(); + } + } + presets.append(preset); + } else { + qCWarning(dcBose()) << "Presets: unhandled XML element" << xml.name(); xml.skipCurrentElement(); } } - emit presetsReceived(requestId, preset); + emit presetsReceived(requestId, presets); } else if (xml.name() == "group") { GroupObject group; diff --git a/bose/soundtouch.h b/bose/soundtouch.h index e2231b3c..eebaa985 100644 --- a/bose/soundtouch.h +++ b/bose/soundtouch.h @@ -60,7 +60,7 @@ public: QUuid getPresets(); //Get information related to the user's SoundTouch presets. //ACTIONS - QUuid setKey(KEY_VALUE keyValue); //Start and control playback on a product. + QUuid setKey(KEY_VALUE keyValue, bool pressed); //Start and control playback on a product. QUuid setVolume(int volume); //Set the volume of a product. QUuid setSource(ContentItemObject contentItem); //Select a product's source. QUuid setZone(ZoneObject zone); //Create a zone of synced products. @@ -95,7 +95,7 @@ signals: void zoneReceived(QUuid requestId, ZoneObject); void bassCapabilitiesReceived(QUuid requestId, BassCapabilitiesObject bassCapabilities); void bassReceived(QUuid requestId, BassObject bass); - void presetsReceived(QUuid requestId, PresetObject presets); + void presetsReceived(QUuid requestId, QList presets); void groupReceived(QUuid requestId, GroupObject group); void requestExecuted(QUuid requestId, bool success);