2020-10-11 00:11:55 +00:00
|
|
|
/* 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/>.
|
|
|
|
*/
|
2020-07-13 11:40:39 +00:00
|
|
|
#include "MusicService.h"
|
2020-11-15 14:05:51 +00:00
|
|
|
#include "systemtask/SystemTask.h"
|
2020-07-13 11:40:39 +00:00
|
|
|
|
|
|
|
int MSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
2020-10-11 00:11:55 +00:00
|
|
|
auto musicService = static_cast<Pinetime::Controllers::MusicService *>(arg);
|
2020-07-13 11:40:39 +00:00
|
|
|
return musicService->OnCommand(conn_handle, attr_handle, ctxt);
|
|
|
|
}
|
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask &system) : m_system(system) {
|
2021-01-19 20:17:03 +00:00
|
|
|
msUuid.value[14] = msId[0];
|
|
|
|
msUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msEventCharUuid.value[12] = msEventCharId[0];
|
|
|
|
msEventCharUuid.value[13] = msEventCharId[1];
|
|
|
|
msEventCharUuid.value[14] = msId[0];
|
|
|
|
msEventCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msStatusCharUuid.value[12] = msStatusCharId[0];
|
|
|
|
msStatusCharUuid.value[13] = msStatusCharId[1];
|
|
|
|
msStatusCharUuid.value[14] = msId[0];
|
|
|
|
msStatusCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msTrackCharUuid.value[12] = msTrackCharId[0];
|
|
|
|
msTrackCharUuid.value[13] = msTrackCharId[1];
|
|
|
|
msTrackCharUuid.value[14] = msId[0];
|
|
|
|
msTrackCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msArtistCharUuid.value[12] = msArtistCharId[0];
|
|
|
|
msArtistCharUuid.value[13] = msArtistCharId[1];
|
|
|
|
msArtistCharUuid.value[14] = msId[0];
|
|
|
|
msArtistCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msAlbumCharUuid.value[12] = msAlbumCharId[0];
|
|
|
|
msAlbumCharUuid.value[13] = msAlbumCharId[1];
|
|
|
|
msAlbumCharUuid.value[14] = msId[0];
|
|
|
|
msAlbumCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msPositionCharUuid.value[12] = msPositionCharId[0];
|
|
|
|
msPositionCharUuid.value[13] = msPositionCharId[1];
|
|
|
|
msPositionCharUuid.value[14] = msId[0];
|
|
|
|
msPositionCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msTotalLengthCharUuid.value[12] = msTotalLengthCharId[0];
|
|
|
|
msTotalLengthCharUuid.value[13] = msTotalLengthCharId[1];
|
|
|
|
msTotalLengthCharUuid.value[14] = msId[0];
|
|
|
|
msTotalLengthCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msTrackNumberCharUuid.value[12] = msTrackNumberCharId[0];
|
|
|
|
msTrackNumberCharUuid.value[13] = msTrackNumberCharId[1];
|
|
|
|
msTrackNumberCharUuid.value[14] = msId[0];
|
|
|
|
msTrackNumberCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msTrackTotalCharUuid.value[12] = msTrackTotalCharId[0];
|
|
|
|
msTrackTotalCharUuid.value[13] = msTrackTotalCharId[1];
|
|
|
|
msTrackTotalCharUuid.value[14] = msId[0];
|
|
|
|
msTrackTotalCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msPlaybackSpeedCharUuid.value[12] = msPlaybackSpeedCharId[0];
|
|
|
|
msPlaybackSpeedCharUuid.value[13] = msPlaybackSpeedCharId[1];
|
|
|
|
msPlaybackSpeedCharUuid.value[14] = msId[0];
|
|
|
|
msPlaybackSpeedCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msRepeatCharUuid.value[12] = msRepeatCharId[0];
|
|
|
|
msRepeatCharUuid.value[13] = msRepeatCharId[1];
|
|
|
|
msRepeatCharUuid.value[14] = msId[0];
|
|
|
|
msRepeatCharUuid.value[15] = msId[1];
|
|
|
|
|
|
|
|
msShuffleCharUuid.value[12] = msShuffleCharId[0];
|
|
|
|
msShuffleCharUuid.value[13] = msShuffleCharId[1];
|
|
|
|
msShuffleCharUuid.value[14] = msId[0];
|
|
|
|
msShuffleCharUuid.value[15] = msId[1];
|
2020-10-11 00:11:55 +00:00
|
|
|
|
|
|
|
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 = "";
|
2021-04-04 15:19:41 +00:00
|
|
|
trackName = "track information..";
|
2020-10-11 00:11:55 +00:00
|
|
|
playing = false;
|
|
|
|
repeat = false;
|
|
|
|
shuffle = false;
|
|
|
|
playbackSpeed = 1.0f;
|
|
|
|
trackProgress = 0;
|
|
|
|
trackLength = 0;
|
2020-07-13 11:40:39 +00:00
|
|
|
}
|
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
void Pinetime::Controllers::MusicService::Init() {
|
2020-07-13 11:40:39 +00:00
|
|
|
int res = 0;
|
|
|
|
res = ble_gatts_count_cfg(serviceDefinition);
|
|
|
|
ASSERT(res == 0);
|
2020-10-11 00:11:55 +00:00
|
|
|
|
2020-07-13 11:40:39 +00:00
|
|
|
res = ble_gatts_add_svcs(serviceDefinition);
|
|
|
|
ASSERT(res == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle,
|
2020-10-11 00:11:55 +00:00
|
|
|
struct ble_gatt_access_ctxt *ctxt) {
|
|
|
|
|
2020-07-13 11:40:39 +00:00
|
|
|
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
|
2020-10-11 00:11:55 +00:00
|
|
|
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];
|
|
|
|
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;
|
|
|
|
}
|
2020-07-13 11:40:39 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
std::string Pinetime::Controllers::MusicService::getAlbum() {
|
|
|
|
return albumName;
|
2020-07-13 11:40:39 +00:00
|
|
|
}
|
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
std::string Pinetime::Controllers::MusicService::getArtist() {
|
|
|
|
return artistName;
|
2020-07-13 11:40:39 +00:00
|
|
|
}
|
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
std::string Pinetime::Controllers::MusicService::getTrack() {
|
|
|
|
return trackName;
|
2020-07-13 11:40:39 +00:00
|
|
|
}
|
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
bool Pinetime::Controllers::MusicService::isPlaying() {
|
|
|
|
return playing;
|
2020-07-20 20:28:21 +00:00
|
|
|
}
|
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
float Pinetime::Controllers::MusicService::getPlaybackSpeed() {
|
|
|
|
return playbackSpeed;
|
|
|
|
}
|
2020-07-13 11:40:39 +00:00
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
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);
|
|
|
|
}
|
2020-07-13 11:40:39 +00:00
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
int Pinetime::Controllers::MusicService::getProgress() {
|
|
|
|
return trackProgress;
|
|
|
|
}
|
2020-07-13 11:40:39 +00:00
|
|
|
|
2020-10-11 00:11:55 +00:00
|
|
|
int Pinetime::Controllers::MusicService::getTrackLength() {
|
|
|
|
return trackLength;
|
2020-07-13 11:40:39 +00:00
|
|
|
}
|
|
|
|
|