diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/ble/MusicService.cpp | 284 | ||||
-rw-r--r-- | src/components/ble/MusicService.h | 216 |
2 files changed, 335 insertions, 165 deletions
diff --git a/src/components/ble/MusicService.cpp b/src/components/ble/MusicService.cpp index 9105a8e6..84f2972b 100644 --- a/src/components/ble/MusicService.cpp +++ b/src/components/ble/MusicService.cpp @@ -1,129 +1,225 @@ +/* Copyright (C) 2020 JF, Adam Pigg, Avamander + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ #include <systemtask/SystemTask.h> #include "MusicService.h" int MSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - auto musicService = static_cast<Pinetime::Controllers::MusicService*>(arg); + auto musicService = static_cast<Pinetime::Controllers::MusicService *>(arg); return musicService->OnCommand(conn_handle, attr_handle, ctxt); } -Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask &system) : m_system(system) -{ - msUuid.value[11] = msId[0]; - msUuid.value[12] = msId[1]; - msEventCharUuid.value[11] = msEventCharId[0]; - msEventCharUuid.value[12] = msEventCharId[1]; - msStatusCharUuid.value[11] = msStatusCharId[0]; - msStatusCharUuid.value[12] = msStatusCharId[1]; - msTrackCharUuid.value[11] = msTrackCharId[0]; - msTrackCharUuid.value[12] = msTrackCharId[1]; - msArtistCharUuid.value[11] = msArtistCharId[0]; - msArtistCharUuid.value[12] = msArtistCharId[1]; - msAlbumCharUuid.value[11] = msAlbumCharId[0]; - msAlbumCharUuid.value[12] = msAlbumCharId[1]; - - characteristicDefinition[0] = { .uuid = (ble_uuid_t*)(&msEventCharUuid), - .access_cb = MSCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_NOTIFY, - .val_handle = &m_eventHandle - }; - characteristicDefinition[1] = { .uuid = (ble_uuid_t*)(&msStatusCharUuid), - .access_cb = MSCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ - }; - characteristicDefinition[2] = { .uuid = (ble_uuid_t*)(&msTrackCharUuid), - .access_cb = MSCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ - }; - characteristicDefinition[3] = { .uuid = (ble_uuid_t*)(&msArtistCharUuid), - .access_cb = MSCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ - }; - characteristicDefinition[4] = { .uuid = (ble_uuid_t*)(&msAlbumCharUuid), - .access_cb = MSCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ - }; - characteristicDefinition[5] = {0}; - - serviceDefinition[0] = { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t *) &msUuid, - .characteristics = characteristicDefinition - }; - serviceDefinition[1] = {0}; - - m_artist = "Waiting for"; - m_album = ""; - m_track = "track information..."; +Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask &system) : m_system(system) { + msUuid.value[11] = msId[0]; + msUuid.value[12] = msId[1]; + msEventCharUuid.value[11] = msEventCharId[0]; + msEventCharUuid.value[12] = msEventCharId[1]; + msStatusCharUuid.value[11] = msStatusCharId[0]; + msStatusCharUuid.value[12] = msStatusCharId[1]; + msTrackCharUuid.value[11] = msTrackCharId[0]; + msTrackCharUuid.value[12] = msTrackCharId[1]; + msArtistCharUuid.value[11] = msArtistCharId[0]; + msArtistCharUuid.value[12] = msArtistCharId[1]; + msAlbumCharUuid.value[11] = msAlbumCharId[0]; + msAlbumCharUuid.value[12] = msAlbumCharId[1]; + msPositionCharUuid.value[11] = msPositionCharId[0]; + msPositionCharUuid.value[12] = msPositionCharId[1]; + msTotalLengthCharUuid.value[11] = msTotalLengthCharId[0]; + msTotalLengthCharUuid.value[12] = msTotalLengthCharId[1]; + msTrackNumberCharUuid.value[11] = msTrackNumberCharId[0]; + msTrackNumberCharUuid.value[12] = msTrackNumberCharId[1]; + msTrackTotalCharUuid.value[11] = msTrackTotalCharId[0]; + msTrackTotalCharUuid.value[12] = msTrackTotalCharId[1]; + msPlaybackSpeedCharUuid.value[11] = msPlaybackSpeedCharId[0]; + msPlaybackSpeedCharUuid.value[12] = msPlaybackSpeedCharId[1]; + msRepeatCharUuid.value[11] = msRepeatCharId[0]; + msRepeatCharUuid.value[12] = msRepeatCharId[1]; + msShuffleCharUuid.value[11] = msShuffleCharId[0]; + msShuffleCharUuid.value[12] = msShuffleCharId[1]; + + characteristicDefinition[0] = {.uuid = (ble_uuid_t *) (&msEventCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_NOTIFY, + .val_handle = &eventHandle + }; + characteristicDefinition[1] = {.uuid = (ble_uuid_t *) (&msStatusCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[2] = {.uuid = (ble_uuid_t *) (&msTrackCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[3] = {.uuid = (ble_uuid_t *) (&msArtistCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[4] = {.uuid = (ble_uuid_t *) (&msAlbumCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[5] = {.uuid = (ble_uuid_t *) (&msPositionCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[6] = {.uuid = (ble_uuid_t *) (&msTotalLengthCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[7] = {.uuid = (ble_uuid_t *) (&msTotalLengthCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[8] = {.uuid = (ble_uuid_t *) (&msTrackNumberCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[9] = {.uuid = (ble_uuid_t *) (&msTrackTotalCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[10] = {.uuid = (ble_uuid_t *) (&msPlaybackSpeedCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[11] = {.uuid = (ble_uuid_t *) (&msRepeatCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[12] = {.uuid = (ble_uuid_t *) (&msShuffleCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[13] = {0}; + + serviceDefinition[0] = { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = (ble_uuid_t *) &msUuid, + .characteristics = characteristicDefinition + }; + serviceDefinition[1] = {0}; + + artistName = "Waiting for"; + albumName = ""; + trackName = "track information..."; + playing = false; + repeat = false; + shuffle = false; + playbackSpeed = 1.0f; + trackProgress = 0; + trackLength = 0; } -void Pinetime::Controllers::MusicService::Init() -{ +void Pinetime::Controllers::MusicService::Init() { int res = 0; res = ble_gatts_count_cfg(serviceDefinition); ASSERT(res == 0); - + res = ble_gatts_add_svcs(serviceDefinition); ASSERT(res == 0); } int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt) { - + struct ble_gatt_access_ctxt *ctxt) { + if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - size_t notifSize = OS_MBUF_PKTLEN(ctxt->om); - uint8_t data[notifSize + 1]; - data[notifSize] = '\0'; - os_mbuf_copydata(ctxt->om, 0, notifSize, data); - char *s = (char *) &data[0]; - NRF_LOG_INFO("DATA : %s", s); - if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msArtistCharUuid) == 0) { - m_artist = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msTrackCharUuid) == 0) { - m_track = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msAlbumCharUuid) == 0) { - m_album = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msStatusCharUuid) == 0) { - m_status = s[0]; - } + size_t notifSize = OS_MBUF_PKTLEN(ctxt->om); + uint8_t data[notifSize + 1]; + data[notifSize] = '\0'; + os_mbuf_copydata(ctxt->om, 0, notifSize, data); + char *s = (char *) &data[0]; + NRF_LOG_INFO("DATA : %s", s); + if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msArtistCharUuid) == 0) { + artistName = s; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTrackCharUuid) == 0) { + trackName = s; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msAlbumCharUuid) == 0) { + albumName = s; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msStatusCharUuid) == 0) { + playing = s[0]; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msRepeatCharUuid) == 0) { + repeat = s[0]; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msShuffleCharUuid) == 0) { + shuffle = s[0]; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msPositionCharUuid) == 0) { + trackProgress = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTotalLengthCharUuid) == 0) { + trackLength = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTrackNumberCharUuid) == 0) { + trackNumber = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTrackTotalCharUuid) == 0) { + tracksTotal = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msPlaybackSpeedCharUuid) == 0) { + playbackSpeed = static_cast<float>(((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3])) / 100.0f; + } } return 0; } -std::string Pinetime::Controllers::MusicService::album() -{ - return m_album; +std::string Pinetime::Controllers::MusicService::getAlbum() { + return albumName; } -std::string Pinetime::Controllers::MusicService::artist() -{ - return m_artist; +std::string Pinetime::Controllers::MusicService::getArtist() { + return artistName; } -std::string Pinetime::Controllers::MusicService::track() -{ - return m_track; +std::string Pinetime::Controllers::MusicService::getTrack() { + return trackName; } -unsigned char Pinetime::Controllers::MusicService::status() -{ - return m_status; +bool Pinetime::Controllers::MusicService::isPlaying() { + return playing; } -void Pinetime::Controllers::MusicService::event(char event) -{ - auto *om = ble_hs_mbuf_from_flat(&event, 1); +float Pinetime::Controllers::MusicService::getPlaybackSpeed() { + return playbackSpeed; +} - uint16_t connectionHandle = m_system.nimble().connHandle(); +void Pinetime::Controllers::MusicService::event(char event) { + auto *om = ble_hs_mbuf_from_flat(&event, 1); + + uint16_t connectionHandle = m_system.nimble().connHandle(); + + if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) { + return; + } + + ble_gattc_notify_custom(connectionHandle, eventHandle, om); +} - if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) { - return; - } +int Pinetime::Controllers::MusicService::getProgress() { + return trackProgress; +} - ble_gattc_notify_custom(connectionHandle, m_eventHandle, om); +int Pinetime::Controllers::MusicService::getTrackLength() { + return trackLength; } diff --git a/src/components/ble/MusicService.h b/src/components/ble/MusicService.h index ab6db572..b365909b 100644 --- a/src/components/ble/MusicService.h +++ b/src/components/ble/MusicService.h @@ -1,3 +1,20 @@ +/* Copyright (C) 2020 JF, Adam Pigg, Avamander + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ #pragma once #include <cstdint> @@ -14,78 +31,135 @@ namespace Pinetime { class SystemTask; } namespace Controllers { - + class MusicService { - public: - MusicService(Pinetime::System::SystemTask &system); - void Init(); - int OnCommand(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt); - - std::string artist(); - std::string track(); - std::string album(); - unsigned char status(); - - void event(char event); - - static const char EVENT_MUSIC_OPEN = 0xe0; - static const char EVENT_MUSIC_PLAY = 0x00; - static const char EVENT_MUSIC_PAUSE = 0x01; - static const char EVENT_MUSIC_NEXT = 0x03; - static const char EVENT_MUSIC_PREV = 0x04; - static const char EVENT_MUSIC_VOLUP = 0x05; - static const char EVENT_MUSIC_VOLDOWN = 0x06; - static const char STATUS_MUSIC_PAUSED = 0x00; - static const char STATUS_MUSIC_PLAYING = 0x01; - - private: - static constexpr uint8_t msId[2] = {0x00, 0x01}; - static constexpr uint8_t msEventCharId[2] = {0x00, 0x02}; - static constexpr uint8_t msStatusCharId[2] = {0x00, 0x03}; - static constexpr uint8_t msArtistCharId[2] = {0x00, 0x04}; - static constexpr uint8_t msTrackCharId[2] = {0x00, 0x05}; - static constexpr uint8_t msAlbumCharId[2] = {0x00, 0x06}; - - ble_uuid128_t msUuid { - .u = { .type = BLE_UUID_TYPE_128 }, - .value = MUSIC_SERVICE_UUID_BASE - }; - - ble_uuid128_t msEventCharUuid { - .u = { .type = BLE_UUID_TYPE_128 }, - .value = MUSIC_SERVICE_UUID_BASE - }; - ble_uuid128_t msStatusCharUuid { - .u = { .type = BLE_UUID_TYPE_128 }, - .value = MUSIC_SERVICE_UUID_BASE - }; - ble_uuid128_t msArtistCharUuid { - .u = { .type = BLE_UUID_TYPE_128 }, - .value = MUSIC_SERVICE_UUID_BASE - }; - ble_uuid128_t msTrackCharUuid { - .u = { .type = BLE_UUID_TYPE_128 }, - .value = MUSIC_SERVICE_UUID_BASE - }; - ble_uuid128_t msAlbumCharUuid { - .u = { .type = BLE_UUID_TYPE_128 }, - .value = MUSIC_SERVICE_UUID_BASE - }; - - struct ble_gatt_chr_def characteristicDefinition[6]; - struct ble_gatt_svc_def serviceDefinition[2]; - - uint16_t m_eventHandle; - - std::string m_artist; - std::string m_album; - std::string m_track; - - unsigned char m_status; - - Pinetime::System::SystemTask& m_system; - + public: + explicit MusicService(Pinetime::System::SystemTask &system); + + void Init(); + + int OnCommand(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt); + + void event(char event); + + std::string getArtist(); + + std::string getTrack(); + + std::string getAlbum(); + + int getProgress(); + + int getTrackLength(); + + float getPlaybackSpeed(); + + bool isPlaying(); + + static const char EVENT_MUSIC_OPEN = 0xe0; + static const char EVENT_MUSIC_PLAY = 0x00; + static const char EVENT_MUSIC_PAUSE = 0x01; + static const char EVENT_MUSIC_NEXT = 0x03; + static const char EVENT_MUSIC_PREV = 0x04; + static const char EVENT_MUSIC_VOLUP = 0x05; + static const char EVENT_MUSIC_VOLDOWN = 0x06; + + enum MusicStatus { + NotPlaying = 0x00, + Playing = 0x01 + }; + private: + static constexpr uint8_t msId[2] = {0x00, 0x01}; + static constexpr uint8_t msEventCharId[2] = {0x00, 0x02}; + static constexpr uint8_t msStatusCharId[2] = {0x00, 0x03}; + static constexpr uint8_t msArtistCharId[2] = {0x00, 0x04}; + static constexpr uint8_t msTrackCharId[2] = {0x00, 0x05}; + static constexpr uint8_t msAlbumCharId[2] = {0x00, 0x06}; + static constexpr uint8_t msPositionCharId[2] = {0x00, 0x07}; + static constexpr uint8_t msTotalLengthCharId[2] = {0x00, 0x08}; + static constexpr uint8_t msTrackNumberCharId[2] = {0x00, 0x09}; + static constexpr uint8_t msTrackTotalCharId[2] = {0x00, 0x0a}; + static constexpr uint8_t msPlaybackSpeedCharId[2] = {0x00, 0x0b}; + static constexpr uint8_t msRepeatCharId[2] = {0x00, 0x0c}; + static constexpr uint8_t msShuffleCharId[2] = {0x00, 0x0d}; + + ble_uuid128_t msUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + + ble_uuid128_t msEventCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msStatusCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msArtistCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msTrackCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msAlbumCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msPositionCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msTotalLengthCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msTrackNumberCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msTrackTotalCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msPlaybackSpeedCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msRepeatCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msShuffleCharUuid{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = MUSIC_SERVICE_UUID_BASE + }; + + struct ble_gatt_chr_def characteristicDefinition[14]; + struct ble_gatt_svc_def serviceDefinition[2]; + + uint16_t eventHandle; + + std::string artistName; + std::string albumName; + std::string trackName; + + bool playing; + + int trackProgress; + int trackLength; + int trackNumber; + int tracksTotal; + + float playbackSpeed; + + bool repeat; + bool shuffle; + + Pinetime::System::SystemTask &m_system; }; } } |