From 7f894f16352091f7251b016694404b1a48c8e0a1 Mon Sep 17 00:00:00 2001 From: Philippe G Date: Fri, 24 Dec 2021 21:56:42 -0800 Subject: [PATCH] finhsing CSpot integration --- components/spotify/Shim.cpp | 13 +-- .../spotify/cspot/include/SpircController.h | 1 + .../spotify/cspot/include/SpotifyTrack.h | 1 + .../spotify/cspot/protocol/metadata.proto | 2 +- .../spotify/cspot/protos/ReflectTypeInfo.cpp | 40 ++++---- .../spotify/cspot/protos/ReflectionInternal.h | 24 ++--- components/spotify/cspot/protos/protobuf.h | 92 +++++++++---------- .../spotify/cspot/src/SpircController.cpp | 2 + components/spotify/cspot/src/SpotifyTrack.cpp | 5 +- components/spotify/cspot_sink.c | 9 +- components/spotify/cspot_sink.h | 2 +- 11 files changed, 102 insertions(+), 89 deletions(-) diff --git a/components/spotify/Shim.cpp b/components/spotify/Shim.cpp index 513f7e1a..e5a99bdb 100644 --- a/components/spotify/Shim.cpp +++ b/components/spotify/Shim.cpp @@ -110,7 +110,6 @@ static void cspotTask(void *pvParameters) { if (token.size() > 0 && cspot.cHandler(CSPOT_SETUP, 44100)) { auto audioSink = std::make_shared(); - // @TODO Actually store this token somewhere mercuryManager = std::make_shared(std::move(session)); mercuryManager->startTask(); @@ -120,7 +119,7 @@ static void cspotTask(void *pvParameters) { switch (event.eventType) { case CSpotEventType::TRACK_INFO: { TrackInfo track = std::get(event.data); - cspot.cHandler(CSPOT_TRACK, 44100, track.artist.c_str(), track.album.c_str(), track.name.c_str()); + cspot.cHandler(CSPOT_TRACK, 44100, track.duration, track.artist.c_str(), track.album.c_str(), track.name.c_str()); break; } case CSpotEventType::PLAY_PAUSE: { @@ -129,6 +128,9 @@ static void cspotTask(void *pvParameters) { else cspot.cHandler(CSPOT_PLAY); break; } + case CSpotEventType::LOAD: + cspot.cHandler(CSPOT_LOAD, std::get(event.data), -1); + break; case CSpotEventType::SEEK: cspot.cHandler(CSPOT_SEEK, std::get(event.data)); break; @@ -165,12 +167,11 @@ static void cspotTask(void *pvParameters) { spircController.reset(); } - // release auth blob + // release auth blob and flush files cspot.blob.reset(); - - // flush files file->flush(); -ESP_LOGW(TAG, "THIS SESSION IS FINISHED %ld %ld %ld", mercuryManager.use_count(), spircController.use_count(), cspot.blob.use_count()); + + ESP_LOGI(TAG, "Shutting down CSpot player"); } // we should not be here diff --git a/components/spotify/cspot/include/SpircController.h b/components/spotify/cspot/include/SpircController.h index 3d98681b..7375e840 100644 --- a/components/spotify/cspot/include/SpircController.h +++ b/components/spotify/cspot/include/SpircController.h @@ -24,6 +24,7 @@ enum class CSpotEventType { NEXT, PREV, SEEK, + LOAD, }; struct CSpotEvent { diff --git a/components/spotify/cspot/include/SpotifyTrack.h b/components/spotify/cspot/include/SpotifyTrack.h index f8f112f8..3b78adb8 100644 --- a/components/spotify/cspot/include/SpotifyTrack.h +++ b/components/spotify/cspot/include/SpotifyTrack.h @@ -20,6 +20,7 @@ struct TrackInfo { std::string album; std::string artist; std::string imageUrl; + int duration; }; typedef std::function trackChangedCallback; diff --git a/components/spotify/cspot/protocol/metadata.proto b/components/spotify/cspot/protocol/metadata.proto index e30bc6b8..9bb2d02d 100644 --- a/components/spotify/cspot/protocol/metadata.proto +++ b/components/spotify/cspot/protocol/metadata.proto @@ -34,7 +34,7 @@ message Track { optional string name = 2; optional Album album = 0x3; repeated Artist artist = 0x4; - optional sint32 duration = 7; + optional sint32 duration = 0x7; repeated Restriction restriction = 0xb; repeated AudioFile file = 0xc; repeated Track alternative = 0xd; diff --git a/components/spotify/cspot/protos/ReflectTypeInfo.cpp b/components/spotify/cspot/protos/ReflectTypeInfo.cpp index c9499c14..dc325ebf 100644 --- a/components/spotify/cspot/protos/ReflectTypeInfo.cpp +++ b/components/spotify/cspot/protos/ReflectTypeInfo.cpp @@ -9,18 +9,18 @@ ReflectType::ofEnum(/* mine id */ ReflectTypeID::EnumReflectTypeID, /* name */ " ReflectEnumValue("EnumReflectTypeKind", 4), ReflectEnumValue("VectorOfClassReflectField", 5), ReflectEnumValue("VectorOfClassReflectEnumValue", 6), - ReflectEnumValue("Double", 7), - ReflectEnumValue("Uint32", 8), - ReflectEnumValue("Char", 9), - ReflectEnumValue("UnsignedChar", 10), - ReflectEnumValue("Float", 11), - ReflectEnumValue("Bool", 12), - ReflectEnumValue("String", 13), - ReflectEnumValue("Int32", 14), - ReflectEnumValue("Int64", 15), - ReflectEnumValue("Int", 16), - ReflectEnumValue("Uint8", 17), - ReflectEnumValue("Uint64", 18), + ReflectEnumValue("Int32", 7), + ReflectEnumValue("Int64", 8), + ReflectEnumValue("Uint32", 9), + ReflectEnumValue("Uint8", 10), + ReflectEnumValue("Int", 11), + ReflectEnumValue("UnsignedChar", 12), + ReflectEnumValue("Float", 13), + ReflectEnumValue("String", 14), + ReflectEnumValue("Uint64", 15), + ReflectEnumValue("Char", 16), + ReflectEnumValue("Double", 17), + ReflectEnumValue("Bool", 18), ReflectEnumValue("VectorOfUint8", 19), ReflectEnumValue("EnumCpuFamily", 20), ReflectEnumValue("EnumOs", 21), @@ -174,18 +174,18 @@ ReflectType::ofEnum(/* mine id */ ReflectTypeID::EnumReflectTypeKind, /* name */ , -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Double, /* name */ "double", /* size */ sizeof(double)), -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Uint32, /* name */ "uint32_t", /* size */ sizeof(uint32_t)), -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Char, /* name */ "char", /* size */ sizeof(char)), -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::UnsignedChar, /* name */ "unsigned char", /* size */ sizeof(unsigned char)), -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Float, /* name */ "float", /* size */ sizeof(float)), -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Bool, /* name */ "bool", /* size */ sizeof(bool)), -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::String, /* name */ "std::string", /* size */ sizeof(std::string)), ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Int32, /* name */ "int32_t", /* size */ sizeof(int32_t)), ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Int64, /* name */ "int64_t", /* size */ sizeof(int64_t)), -ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Int, /* name */ "int", /* size */ sizeof(int)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Uint32, /* name */ "uint32_t", /* size */ sizeof(uint32_t)), ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Uint8, /* name */ "uint8_t", /* size */ sizeof(uint8_t)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Int, /* name */ "int", /* size */ sizeof(int)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::UnsignedChar, /* name */ "unsigned char", /* size */ sizeof(unsigned char)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Float, /* name */ "float", /* size */ sizeof(float)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::String, /* name */ "std::string", /* size */ sizeof(std::string)), ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Uint64, /* name */ "uint64_t", /* size */ sizeof(uint64_t)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Char, /* name */ "char", /* size */ sizeof(char)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Double, /* name */ "double", /* size */ sizeof(double)), +ReflectType::ofPrimitive(/* type id */ ReflectTypeID::Bool, /* name */ "bool", /* size */ sizeof(bool)), ReflectType::ofVector( /* mine typeId */ ReflectTypeID::VectorOfUint8, diff --git a/components/spotify/cspot/protos/ReflectionInternal.h b/components/spotify/cspot/protos/ReflectionInternal.h index 47d9a65c..05e0b61c 100644 --- a/components/spotify/cspot/protos/ReflectionInternal.h +++ b/components/spotify/cspot/protos/ReflectionInternal.h @@ -11,18 +11,18 @@ ClassReflectType = 3, EnumReflectTypeKind = 4, VectorOfClassReflectField = 5, VectorOfClassReflectEnumValue = 6, -Double = 7, -Uint32 = 8, -Char = 9, -UnsignedChar = 10, -Float = 11, -Bool = 12, -String = 13, -Int32 = 14, -Int64 = 15, -Int = 16, -Uint8 = 17, -Uint64 = 18, +Int32 = 7, +Int64 = 8, +Uint32 = 9, +Uint8 = 10, +Int = 11, +UnsignedChar = 12, +Float = 13, +String = 14, +Uint64 = 15, +Char = 16, +Double = 17, +Bool = 18, VectorOfUint8 = 19, EnumCpuFamily = 20, EnumOs = 21, diff --git a/components/spotify/cspot/protos/protobuf.h b/components/spotify/cspot/protos/protobuf.h index 9911a78c..8d7ff4c6 100644 --- a/components/spotify/cspot/protos/protobuf.h +++ b/components/spotify/cspot/protos/protobuf.h @@ -113,14 +113,20 @@ class Frame; if constexpr(std::is_same>::value) { return ReflectTypeID::VectorOfClassReflectEnumValue == this->typeID; } else - if constexpr(std::is_same::value) { - return ReflectTypeID::Double == this->typeID; + if constexpr(std::is_same::value) { + return ReflectTypeID::Int32 == this->typeID; + } else + if constexpr(std::is_same::value) { + return ReflectTypeID::Int64 == this->typeID; } else if constexpr(std::is_same::value) { return ReflectTypeID::Uint32 == this->typeID; } else - if constexpr(std::is_same::value) { - return ReflectTypeID::Char == this->typeID; + if constexpr(std::is_same::value) { + return ReflectTypeID::Uint8 == this->typeID; + } else + if constexpr(std::is_same::value) { + return ReflectTypeID::Int == this->typeID; } else if constexpr(std::is_same::value) { return ReflectTypeID::UnsignedChar == this->typeID; @@ -128,27 +134,21 @@ class Frame; if constexpr(std::is_same::value) { return ReflectTypeID::Float == this->typeID; } else - if constexpr(std::is_same::value) { - return ReflectTypeID::Bool == this->typeID; - } else if constexpr(std::is_same::value) { return ReflectTypeID::String == this->typeID; } else - if constexpr(std::is_same::value) { - return ReflectTypeID::Int32 == this->typeID; - } else - if constexpr(std::is_same::value) { - return ReflectTypeID::Int64 == this->typeID; - } else - if constexpr(std::is_same::value) { - return ReflectTypeID::Int == this->typeID; - } else - if constexpr(std::is_same::value) { - return ReflectTypeID::Uint8 == this->typeID; - } else if constexpr(std::is_same::value) { return ReflectTypeID::Uint64 == this->typeID; } else + if constexpr(std::is_same::value) { + return ReflectTypeID::Char == this->typeID; + } else + if constexpr(std::is_same::value) { + return ReflectTypeID::Double == this->typeID; + } else + if constexpr(std::is_same::value) { + return ReflectTypeID::Bool == this->typeID; + } else if constexpr(std::is_same>::value) { return ReflectTypeID::VectorOfUint8 == this->typeID; } else @@ -296,14 +296,20 @@ class Frame; if constexpr(std::is_same>::value) { typeID = ReflectTypeID::VectorOfClassReflectEnumValue; } else - if constexpr(std::is_same::value) { - typeID = ReflectTypeID::Double; + if constexpr(std::is_same::value) { + typeID = ReflectTypeID::Int32; + } else + if constexpr(std::is_same::value) { + typeID = ReflectTypeID::Int64; } else if constexpr(std::is_same::value) { typeID = ReflectTypeID::Uint32; } else - if constexpr(std::is_same::value) { - typeID = ReflectTypeID::Char; + if constexpr(std::is_same::value) { + typeID = ReflectTypeID::Uint8; + } else + if constexpr(std::is_same::value) { + typeID = ReflectTypeID::Int; } else if constexpr(std::is_same::value) { typeID = ReflectTypeID::UnsignedChar; @@ -311,27 +317,21 @@ class Frame; if constexpr(std::is_same::value) { typeID = ReflectTypeID::Float; } else - if constexpr(std::is_same::value) { - typeID = ReflectTypeID::Bool; - } else if constexpr(std::is_same::value) { typeID = ReflectTypeID::String; } else - if constexpr(std::is_same::value) { - typeID = ReflectTypeID::Int32; - } else - if constexpr(std::is_same::value) { - typeID = ReflectTypeID::Int64; - } else - if constexpr(std::is_same::value) { - typeID = ReflectTypeID::Int; - } else - if constexpr(std::is_same::value) { - typeID = ReflectTypeID::Uint8; - } else if constexpr(std::is_same::value) { typeID = ReflectTypeID::Uint64; } else + if constexpr(std::is_same::value) { + typeID = ReflectTypeID::Char; + } else + if constexpr(std::is_same::value) { + typeID = ReflectTypeID::Double; + } else + if constexpr(std::is_same::value) { + typeID = ReflectTypeID::Bool; + } else if constexpr(std::is_same>::value) { typeID = ReflectTypeID::VectorOfUint8; } else @@ -473,18 +473,18 @@ class Frame; ReflectTypeKind *u_EnumReflectTypeKind; std::vector *u_VectorOfClassReflectField; std::vector *u_VectorOfClassReflectEnumValue; - double *u_Double; - uint32_t *u_Uint32; - char *u_Char; - unsigned char *u_UnsignedChar; - float *u_Float; - bool *u_Bool; - std::string *u_String; int32_t *u_Int32; int64_t *u_Int64; - int *u_Int; + uint32_t *u_Uint32; uint8_t *u_Uint8; + int *u_Int; + unsigned char *u_UnsignedChar; + float *u_Float; + std::string *u_String; uint64_t *u_Uint64; + char *u_Char; + double *u_Double; + bool *u_Bool; std::vector *u_VectorOfUint8; CpuFamily *u_EnumCpuFamily; Os *u_EnumOs; diff --git a/components/spotify/cspot/src/SpircController.cpp b/components/spotify/cspot/src/SpircController.cpp index cf83979a..2230b075 100644 --- a/components/spotify/cspot/src/SpircController.cpp +++ b/components/spotify/cspot/src/SpircController.cpp @@ -182,6 +182,7 @@ void SpircController::handleFrame(std::vector &data) { } void SpircController::loadTrack(uint32_t position_ms, bool isPaused) { + sendEvent(CSpotEventType::LOAD, (int) position_ms); state->setPlaybackState(PlaybackState::Loading); std::function loadedLambda = [=]() { // Loading finished, notify that playback started @@ -216,6 +217,7 @@ void SpircController::setEventHandler(cspotEventHandler callback) { info.artist = track.artist; info.imageUrl = track.imageUrl; info.name = track.name; + info.duration = track.duration; this->sendEvent(CSpotEventType::TRACK_INFO, info); }); diff --git a/components/spotify/cspot/src/SpotifyTrack.cpp b/components/spotify/cspot/src/SpotifyTrack.cpp index 3e289ec7..42b9e32d 100644 --- a/components/spotify/cspot/src/SpotifyTrack.cpp +++ b/components/spotify/cspot/src/SpotifyTrack.cpp @@ -99,12 +99,13 @@ void SpotifyTrack::trackInformationCallback(std::unique_ptr res if (trackInfoReceived != nullptr) { - CSPOT_LOG(info, "Calling %d", trackInfo.album.value().cover_group.value().image.size()); TrackInfo simpleTrackInfo = { .name = trackInfo.name.value(), .album = trackInfo.album.value().name.value(), .artist = trackInfo.artist[0].name.value(), - .imageUrl = "https://i.scdn.co/image/" + bytesToHexString(trackInfo.album.value().cover_group.value().image[0].file_id.value()) + .imageUrl = "https://i.scdn.co/image/" + bytesToHexString(trackInfo.album.value().cover_group.value().image[0].file_id.value()), + .duration = trackInfo.duration.value(), + }; trackInfoReceived(simpleTrackInfo); diff --git a/components/spotify/cspot_sink.c b/components/spotify/cspot_sink.c index 69722478..d81379ff 100644 --- a/components/spotify/cspot_sink.c +++ b/components/spotify/cspot_sink.c @@ -90,6 +90,7 @@ const static actrls_t controls = { */ static bool cmd_handler(cspot_event_t event, ...) { va_list args; + static bool loaded = false; va_start(args, event); @@ -115,14 +116,20 @@ static bool cmd_handler(cspot_event_t event, ...) { actrls_unset(); displayer_control(DISPLAYER_SUSPEND); break; + case CSPOT_LOAD: + // this message only appears if we load in the middle of a track + loaded = true; + __attribute__ ((fallthrough)); case CSPOT_SEEK: displayer_timer(DISPLAYER_ELAPSED, va_arg(args, int), -1); break; case CSPOT_TRACK: { uint32_t sample_rate = va_arg(args, uint32_t); + int duration = va_arg(args, int); char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*); displayer_metadata(artist, album, title); - displayer_timer(DISPLAYER_ELAPSED, 0, -1); + displayer_timer(DISPLAYER_ELAPSED, loaded ? -1 : 0, duration); + loaded = false; break; } // nothing to do on CSPOT_FLUSH diff --git a/components/spotify/cspot_sink.h b/components/spotify/cspot_sink.h index 5a4109b3..96703c52 100644 --- a/components/spotify/cspot_sink.h +++ b/components/spotify/cspot_sink.h @@ -16,7 +16,7 @@ extern "C" #endif // STOP means remove playlist, FLUSH means flush audio buffer, DISC means bye-bye -typedef enum { CSPOT_SETUP, CSPOT_DISC, CSPOT_FLUSH, CSPOT_STOP, CSPOT_PLAY, CSPOT_PAUSE, CSPOT_SEEK, CSPOT_TRACK, +typedef enum { CSPOT_SETUP, CSPOT_DISC, CSPOT_FLUSH, CSPOT_STOP, CSPOT_PLAY, CSPOT_PAUSE, CSPOT_SEEK, CSPOT_TRACK, CSPOT_LOAD, CSPOT_VOLUME, CSPOT_VOLUME_UP, CSPOT_VOLUME_DOWN, CSPOT_NEXT, CSPOT_PREV, CSPOT_TOGGLE, } cspot_event_t;