diff --git a/components/display/CMakeLists.txt b/components/display/CMakeLists.txt index 01886005..8a1944b9 100644 --- a/components/display/CMakeLists.txt +++ b/components/display/CMakeLists.txt @@ -2,6 +2,7 @@ idf_component_register(SRC_DIRS . core core/ifaces fonts INCLUDE_DIRS . fonts core REQUIRES platform_config tools esp_common PRIV_REQUIRES services freertos driver + EMBED_FILES note.jpg ) set_source_files_properties(display.c diff --git a/components/display/SH1106.c b/components/display/SH1106.c index 7bd28182..11e69707 100644 --- a/components/display/SH1106.c +++ b/components/display/SH1106.c @@ -86,7 +86,7 @@ static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { Device->WriteCommand( Device, Contrast ); } -static void SPIParams(int Speed, uint8_t *mode, uint8_t *CS_pre, uint8_t *CS_post) { +static void SPIParams(int Speed, uint8_t *mode, uint16_t *CS_pre, uint8_t *CS_post) { *CS_post = Speed / (8*1000*1000); } diff --git a/components/display/core/gds.c b/components/display/core/gds.c index 63e32861..fc1d8d3d 100644 --- a/components/display/core/gds.c +++ b/components/display/core/gds.c @@ -235,12 +235,13 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { ledc_update_duty( LEDC_HIGH_SPEED_MODE, Device->Backlight.Channel ); } } - + void GDS_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { if (Device->SetLayout) Device->SetLayout( Device, HFlip, VFlip, Rotate ); } void GDS_SetDirty( struct GDS_Device* Device ) { Device->Dirty = true; } -int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; } -int GDS_GetHeight( struct GDS_Device* Device ) { return Device ? Device->Height : 0; } -int GDS_GetDepth( struct GDS_Device* Device ) { return Device ? Device->Depth : 0; } -int GDS_GetMode( struct GDS_Device* Device ) { return Device ? Device->Mode : 0; } +int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; } +void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; } +int GDS_GetHeight( struct GDS_Device* Device ) { return Device ? Device->Height : 0; } +int GDS_GetDepth( struct GDS_Device* Device ) { return Device ? Device->Depth : 0; } +int GDS_GetMode( struct GDS_Device* Device ) { return Device ? Device->Mode : 0; } void GDS_DisplayOn( struct GDS_Device* Device ) { if (Device->DisplayOn) Device->DisplayOn( Device ); } void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device->DisplayOff) Device->DisplayOff( Device ); } \ No newline at end of file diff --git a/components/display/core/gds.h b/components/display/core/gds.h index d79ade04..fa782329 100644 --- a/components/display/core/gds.h +++ b/components/display/core/gds.h @@ -38,6 +38,7 @@ void GDS_Update( struct GDS_Device* Device ); void GDS_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ); void GDS_SetDirty( struct GDS_Device* Device ); int GDS_GetWidth( struct GDS_Device* Device ); +void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ); int GDS_GetHeight( struct GDS_Device* Device ); int GDS_GetDepth( struct GDS_Device* Device ); int GDS_GetMode( struct GDS_Device* Device ); diff --git a/components/display/core/gds_font.c b/components/display/core/gds_font.c index 2ea38872..65c1a08e 100644 --- a/components/display/core/gds_font.c +++ b/components/display/core/gds_font.c @@ -73,13 +73,13 @@ void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y, CharStartY+= OffsetY; /* Do not attempt to draw if this character is entirely offscreen */ - if ( CharEndX < 0 || CharStartX >= Device->Width || CharEndY < 0 || CharStartY >= Device->Height ) { + if ( CharEndX < 0 || CharStartX >= Device->TextWidth || CharEndY < 0 || CharStartY >= Device->Height ) { ClipDebug( x, y ); return; } /* Do not attempt to draw past the end of the screen */ - CharEndX = ( CharEndX >= Device->Width ) ? Device->Width - 1 : CharEndX; + CharEndX = ( CharEndX >= Device->TextWidth ) ? Device->TextWidth - 1 : CharEndX; CharEndY = ( CharEndY >= Device->Height ) ? Device->Height - 1 : CharEndY; Device->Dirty = true; @@ -146,7 +146,7 @@ int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character ) { } int GDS_FontGetMaxCharsPerRow( struct GDS_Device* Display ) { - return Display->Width / Display->Font->Width; + return Display->TextWidth / Display->Font->Width; } int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display ) { @@ -210,7 +210,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int switch ( Anchor ) { case TextAnchor_East: { *OutY = ( Display->Height / 2 ) - ( StringHeight / 2 ); - *OutX = ( Display->Width - StringWidth ); + *OutX = ( Display->TextWidth - StringWidth ); break; } @@ -221,19 +221,19 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int break; } case TextAnchor_North: { - *OutX = ( Display->Width / 2 ) - ( StringWidth / 2 ); + *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 ); *OutY = 0; break; } case TextAnchor_South: { - *OutX = ( Display->Width / 2 ) - ( StringWidth / 2 ); + *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 ); *OutY = ( Display->Height - StringHeight ); break; } case TextAnchor_NorthEast: { - *OutX = ( Display->Width - StringWidth ); + *OutX = ( Display->TextWidth - StringWidth ); *OutY = 0; break; @@ -246,7 +246,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int } case TextAnchor_SouthEast: { *OutY = ( Display->Height - StringHeight ); - *OutX = ( Display->Width - StringWidth ); + *OutX = ( Display->TextWidth - StringWidth ); break; } @@ -258,7 +258,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int } case TextAnchor_Center: { *OutY = ( Display->Height / 2 ) - ( StringHeight / 2 ); - *OutX = ( Display->Width / 2 ) - ( StringWidth / 2 ); + *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 ); break; } diff --git a/components/display/core/gds_image.c b/components/display/core/gds_image.c index cbb392e5..f47e3383 100644 --- a/components/display/core/gds_image.c +++ b/components/display/core/gds_image.c @@ -142,7 +142,7 @@ static unsigned OutHandlerDirect(JDEC *Decoder, void *Bitmap, JRECT *Frame) { JpegCtx *Context = (JpegCtx*) Decoder->device; uint8_t *Pixels = (uint8_t*) Bitmap; int Shift = 8 - Context->Depth; - + // decoded image is RGB888, shift only make sense for grayscale if (Context->Mode == GDS_RGB888) { OUTHANDLERDIRECT(Scaler888, 0); @@ -167,7 +167,7 @@ static unsigned OutHandlerDirect(JDEC *Decoder, void *Bitmap, JRECT *Frame) { static void* DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, bool SizeOnly, int RGB_Mode) { JDEC Decoder; JpegCtx Context; - char *Scratch = calloc(SCRATCH_SIZE, 1); + char *Scratch = malloc(SCRATCH_SIZE); if (!Scratch) { ESP_LOGE(TAG, "Cannot allocate workspace"); @@ -372,7 +372,7 @@ bool GDS_DrawJPEG(struct GDS_Device* Device, uint8_t *Source, int x, int y, int JDEC Decoder; JpegCtx Context; bool Ret = false; - char *Scratch = calloc(SCRATCH_SIZE, 1); + char *Scratch = malloc(SCRATCH_SIZE); if (!Scratch) { ESP_LOGE(TAG, "Cannot allocate workspace"); diff --git a/components/display/core/gds_private.h b/components/display/core/gds_private.h index 6b098ebe..17203083 100644 --- a/components/display/core/gds_private.h +++ b/components/display/core/gds_private.h @@ -95,7 +95,7 @@ struct GDS_Device { const struct GDS_FontDef* Font; } Lines[MAX_LINES]; - uint16_t Width; + uint16_t Width, TextWidth; uint16_t Height; uint8_t Depth, Mode; @@ -125,7 +125,7 @@ struct GDS_Device { void (*DrawRGB)( struct GDS_Device* Device, uint8_t *Image,int x, int y, int Width, int Height, int RGB_Mode ); void (*ClearWindow)( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ); // may provide for tweaking - void (*SPIParams)(int Speed, uint8_t *mode, uint8_t *CS_pre, uint8_t *CS_post); + void (*SPIParams)(int Speed, uint8_t *mode, uint16_t *CS_pre, uint8_t *CS_post); // interface-specific methods WriteCommandProc WriteCommand; diff --git a/components/display/core/gds_text.c b/components/display/core/gds_text.c index 468414ba..b2ef8903 100644 --- a/components/display/core/gds_text.c +++ b/components/display/core/gds_text.c @@ -100,13 +100,13 @@ bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Tex Width = GDS_FontMeasureString( Device, Text ); // adjusting position, erase only EoL for rigth-justified - if (Pos == GDS_TEXT_RIGHT) X = Device->Width - Width - 1; - else if (Pos == GDS_TEXT_CENTER) X = (Device->Width - Width) / 2; + if (Pos == GDS_TEXT_RIGHT) X = Device->TextWidth - Width - 1; + else if (Pos == GDS_TEXT_CENTER) X = (Device->TextWidth - Width) / 2; // erase if requested if (Attr & GDS_TEXT_CLEAR) { int Y_min = max(0, Device->Lines[N].Y), Y_max = max(0, Device->Lines[N].Y + Device->Lines[N].Font->Height); - for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->Width; c++) + for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->TextWidth; c++) for (int y = Y_min; y < Y_max; y++) DrawPixelFast( Device, c, y, GDS_COLOR_BLACK ); } @@ -119,7 +119,7 @@ bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Tex Device->Dirty = true; if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device ); - return Width + X < Device->Width; + return Width + X < Device->TextWidth; } /**************************************************************************************** @@ -146,7 +146,7 @@ int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max) { // we might already fit GDS_SetFont( Device, Device->Lines[N].Font ); - if (GDS_FontMeasureString( Device, String ) <= Device->Width) return 0; + if (GDS_FontMeasureString( Device, String ) <= Device->TextWidth) return 0; // add some space for better visual strncat(String, Space, Max-Len); @@ -157,7 +157,7 @@ int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max) { Boundary = GDS_FontMeasureString( Device, String ); // add a full display width - while (Len < Max && GDS_FontMeasureString( Device, String ) - Boundary < Device->Width) { + while (Len < Max && GDS_FontMeasureString( Device, String ) - Boundary < Device->TextWidth) { String[Len++] = String[Extra++]; String[Len] = '\0'; } diff --git a/components/display/core/ifaces/default_if_i2c.c b/components/display/core/ifaces/default_if_i2c.c index 28fd2347..22f5934e 100644 --- a/components/display/core/ifaces/default_if_i2c.c +++ b/components/display/core/ifaces/default_if_i2c.c @@ -75,7 +75,7 @@ bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int Device->RSTPin = RSTPin; Device->Backlight.Pin = BacklightPin; Device->IF = GDS_IF_I2C; - Device->Width = Width; + Device->Width = Device->TextWidth = Width; Device->Height = Height; if ( RSTPin >= 0 ) { diff --git a/components/display/core/ifaces/default_if_spi.c b/components/display/core/ifaces/default_if_spi.c index 968ce51c..1f047584 100644 --- a/components/display/core/ifaces/default_if_spi.c +++ b/components/display/core/ifaces/default_if_spi.c @@ -35,7 +35,7 @@ bool GDS_SPIInit( int SPI, int DC ) { } bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed ) { - spi_device_interface_config_t SPIDeviceConfig; + spi_device_interface_config_t SPIDeviceConfig = { }; spi_device_handle_t SPIDevice; NullCheck( Device, return false ); @@ -45,8 +45,6 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false ); } - memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) ); - SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M; SPIDeviceConfig.spics_io_num = CSPin; SPIDeviceConfig.queue_size = 1; @@ -63,7 +61,7 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int Device->CSPin = CSPin; Device->Backlight.Pin = BackLightPin; Device->IF = GDS_IF_SPI; - Device->Width = Width; + Device->Width = Device->TextWidth = Width; Device->Height = Height; if ( RSTPin >= 0 ) { diff --git a/components/display/display.c b/components/display/display.c index 0d965a44..68d6b86a 100644 --- a/components/display/display.c +++ b/components/display/display.c @@ -20,6 +20,7 @@ #include "gds_draw.h" #include "gds_text.h" #include "gds_font.h" +#include "gds_image.h" static const char *TAG = "display"; @@ -30,6 +31,9 @@ static const char *TAG = "display"; #define SCROLLABLE_SIZE 384 #define HEADER_SIZE 64 #define DEFAULT_SLEEP 3600 +#define ARTWORK_BORDER 1 + +extern const uint8_t default_artwork[] asm("_binary_note_jpg_start"); static EXT_RAM_ATTR struct { TaskHandle_t task; @@ -47,6 +51,12 @@ static EXT_RAM_ATTR struct { char string[8]; // H:MM:SS bool visible; } duration; + struct { + bool enable, fit; + bool updated; + int tick; + int offset; + } artwork; TickType_t tick; } displayer; @@ -147,6 +157,14 @@ void display_init(char *welcome) { GDS_TextSetFontAuto(display, 2, GDS_FONT_LINE_2, -3); displayer.metadata_config = config_alloc_get(NVS_TYPE_STR, "metadata_config"); + + // leave room for artwork is display is horizontal-style + if (strcasestr(displayer.metadata_config, "artwork")) { + displayer.artwork.enable = true; + displayer.artwork.fit = true; + if (height <= 64 && width > height * 2) displayer.artwork.offset = width - height - ARTWORK_BORDER; + PARSE_PARAM(displayer.metadata_config, "artwork", ':', displayer.artwork.fit); + } } free(config); @@ -225,7 +243,12 @@ static void displayer_task(void *args) { // just re-write the whole line it's easier GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, displayer.header); GDS_TextLine(display, 1, GDS_TEXT_RIGHT, GDS_TEXT_UPDATE, _line); - + + // if we have not received artwork after 5s, display a default icon + if (displayer.artwork.enable && !displayer.artwork.updated && tick - displayer.artwork.tick > pdMS_TO_TICKS(5000)) { + ESP_LOGI(TAG, "no artwork received, setting default"); + displayer_artwork((uint8_t*) default_artwork); + } timer_sleep = 1000; } else timer_sleep = max(1000 - elapsed, 0); } else timer_sleep = DEFAULT_SLEEP; @@ -238,6 +261,25 @@ static void displayer_task(void *args) { } } +/**************************************************************************************** + * + */ +void displayer_artwork(uint8_t *data) { + if (!displayer.artwork.enable) return; + + int x = displayer.artwork.offset ? displayer.artwork.offset + ARTWORK_BORDER : 0; + int y = x ? 0 : 32; + GDS_ClearWindow(display, x, y, -1, -1, GDS_COLOR_BLACK); + if (data) { + displayer.artwork.updated = true; + GDS_DrawJPEG(display, data, x, y, GDS_IMAGE_CENTER | (displayer.artwork.fit ? GDS_IMAGE_FIT : 0)); + } else { + displayer.artwork.updated = false; + displayer.artwork.tick = xTaskGetTickCount(); + } + +} + /**************************************************************************************** * */ @@ -378,6 +420,7 @@ void displayer_control(enum displayer_cmd_e cmd, ...) { switch(cmd) { case DISPLAYER_ACTIVATE: { char *header = va_arg(args, char*); + bool artwork = va_arg(args, int); strncpy(displayer.header, header, HEADER_SIZE); displayer.header[HEADER_SIZE] = '\0'; displayer.state = DISPLAYER_ACTIVE; @@ -388,6 +431,7 @@ void displayer_control(enum displayer_cmd_e cmd, ...) { displayer.duration.visible = false; displayer.offset = displayer.boundary = 0; display_bus(&displayer, DISPLAY_BUS_TAKE); + if (artwork) GDS_SetTextWidth(display, displayer.artwork.offset); vTaskResume(displayer.task); break; } @@ -398,6 +442,8 @@ void displayer_control(enum displayer_cmd_e cmd, ...) { break; case DISPLAYER_SHUTDOWN: // let the task self-suspend (we might be doing i2c_write) + GDS_SetTextWidth(display, 0); + GDS_Clear(display, GDS_COLOR_BLACK); displayer.state = DISPLAYER_DOWN; display_bus(&displayer, DISPLAY_BUS_GIVE); break; diff --git a/components/display/display.h b/components/display/display.h index 9c945555..ebb857e7 100644 --- a/components/display/display.h +++ b/components/display/display.h @@ -38,5 +38,6 @@ bool display_is_valid_driver(const char * driver); void displayer_scroll(char *string, int speed, int pause); void displayer_control(enum displayer_cmd_e cmd, ...); void displayer_metadata(char *artist, char *album, char *title); +void displayer_artwork(uint8_t *data); void displayer_timer(enum displayer_time_e mode, int elapsed, int duration); char * display_get_supported_drivers(void); diff --git a/components/display/note.jpg b/components/display/note.jpg new file mode 100644 index 00000000..6beb3ef7 Binary files /dev/null and b/components/display/note.jpg differ diff --git a/components/driver_bt/bt_app_sink.c b/components/driver_bt/bt_app_sink.c index e741f108..7a3a866b 100644 --- a/components/driver_bt/bt_app_sink.c +++ b/components/driver_bt/bt_app_sink.c @@ -172,7 +172,7 @@ static bool cmd_handler(bt_sink_cmd_t cmd, ...) { // now handle events for display switch(cmd) { case BT_SINK_AUDIO_STARTED: - displayer_control(DISPLAYER_ACTIVATE, "BLUETOOTH"); + displayer_control(DISPLAYER_ACTIVATE, "BLUETOOTH", false); break; case BT_SINK_AUDIO_STOPPED: displayer_control(DISPLAYER_SUSPEND); diff --git a/components/raop/raop.c b/components/raop/raop.c index 53679a78..82f5e8b4 100644 --- a/components/raop/raop.c +++ b/components/raop/raop.c @@ -628,6 +628,9 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock) success = ctx->cmd_cb(RAOP_METADATA, metadata.artist, metadata.album, metadata.title); free_metadata(&metadata); } + } else if (body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && strcasestr(p, "image/jpeg")) { + LOG_INFO("[%p]: received JPEG image of %d bytes", ctx, len); + ctx->cmd_cb(RAOP_ARTWORK, body, len); } else { char *dump = kd_dump(headers); LOG_INFO("Unhandled SET PARAMETER\n%s", dump); diff --git a/components/raop/raop_sink.c b/components/raop/raop_sink.c index fe66b365..ea3f02f0 100644 --- a/components/raop/raop_sink.c +++ b/components/raop/raop_sink.c @@ -112,7 +112,7 @@ static bool cmd_handler(raop_event_t event, ...) { switch(event) { case RAOP_SETUP: actrls_set(controls, false, NULL, actrls_ir_action); - displayer_control(DISPLAYER_ACTIVATE, "AIRPLAY"); + displayer_control(DISPLAYER_ACTIVATE, "AIRPLAY", true); break; case RAOP_PLAY: displayer_control(DISPLAYER_TIMER_RUN); @@ -127,8 +127,14 @@ static bool cmd_handler(raop_event_t event, ...) { case RAOP_METADATA: { char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*); displayer_metadata(artist, album, title); + displayer_artwork(NULL); break; } + case RAOP_ARTWORK: { + uint8_t *data = va_arg(args, uint8_t*); + displayer_artwork(data); + break; + } case RAOP_PROGRESS: { int elapsed = va_arg(args, int), duration = va_arg(args, int); displayer_timer(DISPLAYER_ELAPSED, elapsed, duration); diff --git a/components/raop/raop_sink.h b/components/raop/raop_sink.h index a3cb87d4..4f6c5dea 100644 --- a/components/raop/raop_sink.h +++ b/components/raop/raop_sink.h @@ -14,7 +14,7 @@ #define RAOP_SAMPLE_RATE 44100 -typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_METADATA, RAOP_PROGRESS, RAOP_PAUSE, RAOP_STOP, +typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_METADATA, RAOP_ARTWORK, RAOP_PROGRESS, RAOP_PAUSE, RAOP_STOP, RAOP_VOLUME, RAOP_TIMING, RAOP_PREV, RAOP_NEXT, RAOP_REW, RAOP_FWD, RAOP_VOLUME_UP, RAOP_VOLUME_DOWN, RAOP_RESUME, RAOP_TOGGLE } raop_event_t ; diff --git a/components/spotify/Shim.cpp b/components/spotify/Shim.cpp index 87020b8a..fa212257 100644 --- a/components/spotify/Shim.cpp +++ b/components/spotify/Shim.cpp @@ -120,7 +120,8 @@ static void cspotTask(void *pvParameters) { case CSpotEventType::TRACK_INFO: { TrackInfo track = std::get(event.data); // duration is in chunks of 0.5 ms - cspot.cHandler(CSPOT_TRACK, 44100, track.duration / 2, track.artist.c_str(), track.album.c_str(), track.name.c_str()); + cspot.cHandler(CSPOT_TRACK, 44100, track.duration / 2, track.artist.c_str(), + track.album.c_str(), track.name.c_str(), track.imageUrl.c_str()); break; } case CSpotEventType::PLAY_PAUSE: { diff --git a/components/spotify/cspot/CMakeLists.txt b/components/spotify/cspot/CMakeLists.txt index e91c8460..3f5f44ce 100644 --- a/components/spotify/cspot/CMakeLists.txt +++ b/components/spotify/cspot/CMakeLists.txt @@ -45,5 +45,6 @@ endif() add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS}) # PUBLIC to propagate includes from bell to cspot dependents target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC) +target_compile_definitions(bell PUBLIC PB_FIELD_32BIT) target_link_libraries(cspot PUBLIC ${EXTRA_LIBS}) target_include_directories(cspot PUBLIC "include" ${GENERATED_INCLUDES} ${NANOPB_INCLUDE_DIRS}) diff --git a/components/spotify/cspot/bell/CMakeLists.txt b/components/spotify/cspot/bell/CMakeLists.txt index c900048f..2b81a0d4 100644 --- a/components/spotify/cspot/bell/CMakeLists.txt +++ b/components/spotify/cspot/bell/CMakeLists.txt @@ -7,8 +7,6 @@ option(BELL_DISABLE_CODECS "Disable libhelix AAC and MP3 codecs" OFF) #set(BELL_EXTERNAL_CJSON "" CACHE STRING "External cJSON library target name, optional") #set(BELL_EXTERNAL_TREMOR "" CACHE STRING "External tremor library target name, optional") -add_definitions(-DPB_ENABLE_MALLOC) - # Include nanoPB library set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra) find_package(Nanopb REQUIRED) @@ -98,3 +96,4 @@ message(${NANOPB_INCLUDE_DIRS}) # PUBLIC to propagate esp-idf includes to bell dependents target_link_libraries(bell PUBLIC ${EXTRA_LIBS}) target_include_directories(bell PUBLIC "include" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) +target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC) diff --git a/components/spotify/cspot/bell/include/NanoPBHelper.h b/components/spotify/cspot/bell/include/NanoPBHelper.h index d370b199..de6a26b1 100644 --- a/components/spotify/cspot/bell/include/NanoPBHelper.h +++ b/components/spotify/cspot/bell/include/NanoPBHelper.h @@ -42,6 +42,10 @@ void pbDecode(T &result, const pb_msgdesc_t *fields, std::vector &data) } } +void pbPutString(const std::string &stringToPack, char* dst); +void pbPutCharArray(const char * stringToPack, char* dst); +void pbPutBytes(const std::vector &data, pb_bytes_array_t &dst); + const char* pb_encode_to_string(const pb_msgdesc_t *fields, const void *data); pb_istream_t pb_istream_from_http(bell::HTTPClient::HTTPResponse *response, size_t length = 0); diff --git a/components/spotify/cspot/bell/src/NanoPBHelper.cpp b/components/spotify/cspot/bell/src/NanoPBHelper.cpp index c19e031d..0bd4c27d 100644 --- a/components/spotify/cspot/bell/src/NanoPBHelper.cpp +++ b/components/spotify/cspot/bell/src/NanoPBHelper.cpp @@ -47,6 +47,22 @@ pb_bytes_array_t* vectorToPbArray(const std::vector& vectorToPack) return result; } +void pbPutString(const std::string &stringToPack, char* dst) { + stringToPack.copy(dst, stringToPack.size()); + dst[stringToPack.size()] = '\0'; +} + +void pbPutCharArray(const char * stringToPack, char* dst) { + // copy stringToPack into dst + strcpy(dst, stringToPack); + //dst[sizeof(stringToPack)-1] = '\0'; +} + +void pbPutBytes(const std::vector &data, pb_bytes_array_t &dst) { + dst.size = data.size(); + std::copy(data.begin(), data.end(), dst.bytes); +} + std::vector pbArrayToVector(pb_bytes_array_t* pbArray) { return std::vector(pbArray->bytes, pbArray->bytes + pbArray->size); } diff --git a/components/spotify/cspot/include/Packet.h b/components/spotify/cspot/include/Packet.h index 7635db87..d7b828f1 100644 --- a/components/spotify/cspot/include/Packet.h +++ b/components/spotify/cspot/include/Packet.h @@ -9,7 +9,7 @@ class Packet private: public: - Packet(uint8_t command, std::vector &data); + Packet(uint8_t command, const std::vector &data); uint8_t command; std::vector data; }; diff --git a/components/spotify/cspot/protobuf/authentication.options b/components/spotify/cspot/protobuf/authentication.options index f7c08e40..33aad19f 100644 --- a/components/spotify/cspot/protobuf/authentication.options +++ b/components/spotify/cspot/protobuf/authentication.options @@ -1,6 +1,5 @@ -LoginCredentials.username type:FT_POINTER -LoginCredentials.auth_data type:FT_POINTER -LoginCredentials.auth_data type:FT_POINTER -SystemInfo.system_information_string type:FT_POINTER -SystemInfo.device_id type:FT_POINTER -ClientResponseEncrypted.version_string type:FT_POINTER \ No newline at end of file +LoginCredentials.username max_size:30, fixed_length:false +LoginCredentials.auth_data max_size:512, fixed_length:false +SystemInfo.system_information_string max_size:16, fixed_length:false +SystemInfo.device_id max_size:50, fixed_length:false +ClientResponseEncrypted.version_string max_size:32, fixed_length:false \ No newline at end of file diff --git a/components/spotify/cspot/protobuf/authentication.pb.c b/components/spotify/cspot/protobuf/authentication.pb.c index b45976af..3e9fd652 100644 --- a/components/spotify/cspot/protobuf/authentication.pb.c +++ b/components/spotify/cspot/protobuf/authentication.pb.c @@ -9,7 +9,7 @@ PB_BIND(SystemInfo, SystemInfo, 2) -PB_BIND(LoginCredentials, LoginCredentials, AUTO) +PB_BIND(LoginCredentials, LoginCredentials, 2) PB_BIND(ClientResponseEncrypted, ClientResponseEncrypted, 2) diff --git a/components/spotify/cspot/protobuf/authentication.pb.h b/components/spotify/cspot/protobuf/authentication.pb.h index a331adfb..e3eb8e91 100644 --- a/components/spotify/cspot/protobuf/authentication.pb.h +++ b/components/spotify/cspot/protobuf/authentication.pb.h @@ -58,23 +58,25 @@ typedef enum _AuthenticationType { } AuthenticationType; /* Struct definitions */ +typedef PB_BYTES_ARRAY_T(512) LoginCredentials_auth_data_t; typedef struct _LoginCredentials { - char *username; + char username[30]; AuthenticationType typ; - pb_bytes_array_t *auth_data; + LoginCredentials_auth_data_t auth_data; } LoginCredentials; typedef struct _SystemInfo { CpuFamily cpu_family; Os os; - char *system_information_string; - char *device_id; + char system_information_string[16]; + char device_id[50]; } SystemInfo; typedef struct _ClientResponseEncrypted { LoginCredentials login_credentials; SystemInfo system_info; - char *version_string; + bool has_version_string; + char version_string[32]; } ClientResponseEncrypted; @@ -97,12 +99,12 @@ extern "C" { #endif /* Initializer values for message structs */ -#define SystemInfo_init_default {_CpuFamily_MIN, _Os_MIN, NULL, NULL} -#define LoginCredentials_init_default {NULL, _AuthenticationType_MIN, NULL} -#define ClientResponseEncrypted_init_default {LoginCredentials_init_default, SystemInfo_init_default, NULL} -#define SystemInfo_init_zero {_CpuFamily_MIN, _Os_MIN, NULL, NULL} -#define LoginCredentials_init_zero {NULL, _AuthenticationType_MIN, NULL} -#define ClientResponseEncrypted_init_zero {LoginCredentials_init_zero, SystemInfo_init_zero, NULL} +#define SystemInfo_init_default {_CpuFamily_MIN, _Os_MIN, "", ""} +#define LoginCredentials_init_default {"", _AuthenticationType_MIN, {0, {0}}} +#define ClientResponseEncrypted_init_default {LoginCredentials_init_default, SystemInfo_init_default, false, ""} +#define SystemInfo_init_zero {_CpuFamily_MIN, _Os_MIN, "", ""} +#define LoginCredentials_init_zero {"", _AuthenticationType_MIN, {0, {0}}} +#define ClientResponseEncrypted_init_zero {LoginCredentials_init_zero, SystemInfo_init_zero, false, ""} /* Field tags (for use in manual encoding/decoding) */ #define LoginCredentials_username_tag 10 @@ -120,22 +122,22 @@ extern "C" { #define SystemInfo_FIELDLIST(X, a) \ X(a, STATIC, REQUIRED, UENUM, cpu_family, 10) \ X(a, STATIC, REQUIRED, UENUM, os, 60) \ -X(a, POINTER, OPTIONAL, STRING, system_information_string, 90) \ -X(a, POINTER, OPTIONAL, STRING, device_id, 100) +X(a, STATIC, REQUIRED, STRING, system_information_string, 90) \ +X(a, STATIC, REQUIRED, STRING, device_id, 100) #define SystemInfo_CALLBACK NULL #define SystemInfo_DEFAULT NULL #define LoginCredentials_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, STRING, username, 10) \ +X(a, STATIC, REQUIRED, STRING, username, 10) \ X(a, STATIC, REQUIRED, UENUM, typ, 20) \ -X(a, POINTER, OPTIONAL, BYTES, auth_data, 30) +X(a, STATIC, REQUIRED, BYTES, auth_data, 30) #define LoginCredentials_CALLBACK NULL #define LoginCredentials_DEFAULT NULL #define ClientResponseEncrypted_FIELDLIST(X, a) \ X(a, STATIC, REQUIRED, MESSAGE, login_credentials, 10) \ X(a, STATIC, REQUIRED, MESSAGE, system_info, 50) \ -X(a, POINTER, OPTIONAL, STRING, version_string, 70) +X(a, STATIC, OPTIONAL, STRING, version_string, 70) #define ClientResponseEncrypted_CALLBACK NULL #define ClientResponseEncrypted_DEFAULT NULL #define ClientResponseEncrypted_login_credentials_MSGTYPE LoginCredentials @@ -151,9 +153,9 @@ extern const pb_msgdesc_t ClientResponseEncrypted_msg; #define ClientResponseEncrypted_fields &ClientResponseEncrypted_msg /* Maximum encoded size of messages (where known) */ -/* SystemInfo_size depends on runtime parameters */ -/* LoginCredentials_size depends on runtime parameters */ -/* ClientResponseEncrypted_size depends on runtime parameters */ +#define ClientResponseEncrypted_size 665 +#define LoginCredentials_size 550 +#define SystemInfo_size 75 #ifdef __cplusplus } /* extern "C" */ diff --git a/components/spotify/cspot/protobuf/authentication.proto b/components/spotify/cspot/protobuf/authentication.proto index 84d1b2ee..d3896147 100644 --- a/components/spotify/cspot/protobuf/authentication.proto +++ b/components/spotify/cspot/protobuf/authentication.proto @@ -48,14 +48,14 @@ enum AuthenticationType { message SystemInfo { required CpuFamily cpu_family = 0xa; required Os os = 0x3c; - optional string system_information_string = 0x5a; - optional string device_id = 0x64; + required string system_information_string = 0x5a; + required string device_id = 0x64; } message LoginCredentials { - optional string username = 0xa; + required string username = 0xa; required AuthenticationType typ = 0x14; - optional bytes auth_data = 0x1e; + required bytes auth_data = 0x1e; } message ClientResponseEncrypted { diff --git a/components/spotify/cspot/protobuf/mercury.options b/components/spotify/cspot/protobuf/mercury.options index f5a10767..29da3dcb 100644 --- a/components/spotify/cspot/protobuf/mercury.options +++ b/components/spotify/cspot/protobuf/mercury.options @@ -1,2 +1,2 @@ -Header.uri type:FT_POINTER -Header.method type:FT_POINTER +Header.uri max_size:64, fixed_length:false +Header.method max_size:32, fixed_length:false diff --git a/components/spotify/cspot/protobuf/mercury.pb.h b/components/spotify/cspot/protobuf/mercury.pb.h index dabc1980..32e61d09 100644 --- a/components/spotify/cspot/protobuf/mercury.pb.h +++ b/components/spotify/cspot/protobuf/mercury.pb.h @@ -11,8 +11,10 @@ /* Struct definitions */ typedef struct _Header { - char *uri; - char *method; + bool has_uri; + char uri[64]; + bool has_method; + char method[32]; } Header; @@ -21,8 +23,8 @@ extern "C" { #endif /* Initializer values for message structs */ -#define Header_init_default {NULL, NULL} -#define Header_init_zero {NULL, NULL} +#define Header_init_default {false, "", false, ""} +#define Header_init_zero {false, "", false, ""} /* Field tags (for use in manual encoding/decoding) */ #define Header_uri_tag 1 @@ -30,8 +32,8 @@ extern "C" { /* Struct field encoding specification for nanopb */ #define Header_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, STRING, uri, 1) \ -X(a, POINTER, OPTIONAL, STRING, method, 3) +X(a, STATIC, OPTIONAL, STRING, uri, 1) \ +X(a, STATIC, OPTIONAL, STRING, method, 3) #define Header_CALLBACK NULL #define Header_DEFAULT NULL @@ -41,7 +43,7 @@ extern const pb_msgdesc_t Header_msg; #define Header_fields &Header_msg /* Maximum encoded size of messages (where known) */ -/* Header_size depends on runtime parameters */ +#define Header_size 98 #ifdef __cplusplus } /* extern "C" */ diff --git a/components/spotify/cspot/protobuf/metadata.options b/components/spotify/cspot/protobuf/metadata.options index 7504a906..3a6341c8 100644 --- a/components/spotify/cspot/protobuf/metadata.options +++ b/components/spotify/cspot/protobuf/metadata.options @@ -1,18 +1,16 @@ -Track.name type:FT_POINTER -Track.gid type:FT_POINTER -Track.restriction type:FT_POINTER -Track.alternative type:FT_POINTER -Track.file type:FT_POINTER -Track.artist type:FT_POINTER -AudioFile.file_id type:FT_POINTER -Image.file_id type:FT_POINTER -Artist.gid type:FT_POINTER -Artist.name type:FT_POINTER -Album.name type:FT_POINTER -Episode.gid type:FT_POINTER -Episode.name type:FT_POINTER -ImageGroup.image type:FT_POINTER -Episode.audio type:FT_POINTER -Episode.covers type:FT_POINTER -Restriction.countries_allowed type:FT_POINTER -Restriction.countries_forbidden type:FT_POINTER \ No newline at end of file +Track.name max_size: 512 +Track.gid max_size: 64 +Track.file max_count: 16 +Track.artist max_count: 8 +AudioFile.file_id max_size: 128 +Image.file_id max_size: 128 +Artist.gid max_size: 128 +Artist.name max_size: 512 +Album.name max_size: 512 +Episode.gid max_size: 64 +Episode.name max_size: 512 +ImageGroup.image max_count: 10 +Episode.audio max_count: 10 +Episode.covers max_count: 10 +Restriction.countries_allowed max_size: 32 +Restriction.countries_forbidden max_size: 32 \ No newline at end of file diff --git a/components/spotify/cspot/protobuf/metadata.pb.c b/components/spotify/cspot/protobuf/metadata.pb.c index 7196e0cf..78014778 100644 --- a/components/spotify/cspot/protobuf/metadata.pb.c +++ b/components/spotify/cspot/protobuf/metadata.pb.c @@ -15,16 +15,16 @@ PB_BIND(Restriction, Restriction, AUTO) PB_BIND(Image, Image, AUTO) -PB_BIND(ImageGroup, ImageGroup, AUTO) +PB_BIND(ImageGroup, ImageGroup, 2) -PB_BIND(Album, Album, AUTO) +PB_BIND(Album, Album, 2) -PB_BIND(Artist, Artist, AUTO) +PB_BIND(Artist, Artist, 2) -PB_BIND(Track, Track, AUTO) +PB_BIND(Track, Track, 4) PB_BIND(Episode, Episode, 2) diff --git a/components/spotify/cspot/protobuf/metadata.pb.h b/components/spotify/cspot/protobuf/metadata.pb.h index fa196fa8..7def594b 100644 --- a/components/spotify/cspot/protobuf/metadata.pb.h +++ b/components/spotify/cspot/protobuf/metadata.pb.h @@ -24,63 +24,78 @@ typedef enum _AudioFormat { } AudioFormat; /* Struct definitions */ +typedef PB_BYTES_ARRAY_T(128) Artist_gid_t; typedef struct _Artist { - pb_bytes_array_t *gid; - char *name; + bool has_gid; + Artist_gid_t gid; + bool has_name; + char name[512]; } Artist; -typedef struct _Image { - pb_bytes_array_t *file_id; -} Image; - -typedef struct _ImageGroup { - pb_size_t image_count; - struct _Image *image; -} ImageGroup; - -typedef struct _Restriction { - char *countries_allowed; - char *countries_forbidden; -} Restriction; - -typedef struct _Album { - pb_callback_t gid; - char *name; - bool has_cover_group; - ImageGroup cover_group; -} Album; - +typedef PB_BYTES_ARRAY_T(128) AudioFile_file_id_t; typedef struct _AudioFile { - pb_bytes_array_t *file_id; + bool has_file_id; + AudioFile_file_id_t file_id; bool has_format; AudioFormat format; } AudioFile; +typedef PB_BYTES_ARRAY_T(128) Image_file_id_t; +typedef struct _Image { + bool has_file_id; + Image_file_id_t file_id; +} Image; + +typedef struct _Restriction { + bool has_countries_allowed; + char countries_allowed[32]; + bool has_countries_forbidden; + char countries_forbidden[32]; +} Restriction; + +typedef struct _ImageGroup { + pb_size_t image_count; + Image image[10]; +} ImageGroup; + +typedef struct _Album { + pb_callback_t gid; + bool has_name; + char name[512]; + bool has_cover_group; + ImageGroup cover_group; +} Album; + +typedef PB_BYTES_ARRAY_T(64) Episode_gid_t; typedef struct _Episode { - pb_bytes_array_t *gid; - char *name; + bool has_gid; + Episode_gid_t gid; + bool has_name; + char name[512]; bool has_duration; int32_t duration; pb_size_t audio_count; - struct _AudioFile *audio; - struct _ImageGroup *covers; + AudioFile audio[10]; + bool has_covers; + ImageGroup covers; } Episode; +typedef PB_BYTES_ARRAY_T(64) Track_gid_t; typedef struct _Track { - pb_bytes_array_t *gid; - char *name; + bool has_gid; + Track_gid_t gid; + bool has_name; + char name[512]; bool has_album; Album album; pb_size_t artist_count; - struct _Artist *artist; + Artist artist[8]; bool has_duration; int32_t duration; - pb_size_t restriction_count; - struct _Restriction *restriction; + pb_callback_t restriction; pb_size_t file_count; - struct _AudioFile *file; - pb_size_t alternative_count; - struct _Track *alternative; + AudioFile file[16]; + pb_callback_t alternative; } Track; @@ -95,35 +110,35 @@ extern "C" { #endif /* Initializer values for message structs */ -#define AudioFile_init_default {NULL, false, _AudioFormat_MIN} -#define Restriction_init_default {NULL, NULL} -#define Image_init_default {NULL} -#define ImageGroup_init_default {0, NULL} -#define Album_init_default {{{NULL}, NULL}, NULL, false, ImageGroup_init_default} -#define Artist_init_default {NULL, NULL} -#define Track_init_default {NULL, NULL, false, Album_init_default, 0, NULL, false, 0, 0, NULL, 0, NULL, 0, NULL} -#define Episode_init_default {NULL, NULL, false, 0, 0, NULL, NULL} -#define AudioFile_init_zero {NULL, false, _AudioFormat_MIN} -#define Restriction_init_zero {NULL, NULL} -#define Image_init_zero {NULL} -#define ImageGroup_init_zero {0, NULL} -#define Album_init_zero {{{NULL}, NULL}, NULL, false, ImageGroup_init_zero} -#define Artist_init_zero {NULL, NULL} -#define Track_init_zero {NULL, NULL, false, Album_init_zero, 0, NULL, false, 0, 0, NULL, 0, NULL, 0, NULL} -#define Episode_init_zero {NULL, NULL, false, 0, 0, NULL, NULL} +#define AudioFile_init_default {false, {0, {0}}, false, _AudioFormat_MIN} +#define Restriction_init_default {false, "", false, ""} +#define Image_init_default {false, {0, {0}}} +#define ImageGroup_init_default {0, {Image_init_default, Image_init_default, Image_init_default, Image_init_default, Image_init_default, Image_init_default, Image_init_default, Image_init_default, Image_init_default, Image_init_default}} +#define Album_init_default {{{NULL}, NULL}, false, "", false, ImageGroup_init_default} +#define Artist_init_default {false, {0, {0}}, false, ""} +#define Track_init_default {false, {0, {0}}, false, "", false, Album_init_default, 0, {Artist_init_default, Artist_init_default, Artist_init_default, Artist_init_default, Artist_init_default, Artist_init_default, Artist_init_default, Artist_init_default}, false, 0, {{NULL}, NULL}, 0, {AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default}, {{NULL}, NULL}} +#define Episode_init_default {false, {0, {0}}, false, "", false, 0, 0, {AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default, AudioFile_init_default}, false, ImageGroup_init_default} +#define AudioFile_init_zero {false, {0, {0}}, false, _AudioFormat_MIN} +#define Restriction_init_zero {false, "", false, ""} +#define Image_init_zero {false, {0, {0}}} +#define ImageGroup_init_zero {0, {Image_init_zero, Image_init_zero, Image_init_zero, Image_init_zero, Image_init_zero, Image_init_zero, Image_init_zero, Image_init_zero, Image_init_zero, Image_init_zero}} +#define Album_init_zero {{{NULL}, NULL}, false, "", false, ImageGroup_init_zero} +#define Artist_init_zero {false, {0, {0}}, false, ""} +#define Track_init_zero {false, {0, {0}}, false, "", false, Album_init_zero, 0, {Artist_init_zero, Artist_init_zero, Artist_init_zero, Artist_init_zero, Artist_init_zero, Artist_init_zero, Artist_init_zero, Artist_init_zero}, false, 0, {{NULL}, NULL}, 0, {AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero}, {{NULL}, NULL}} +#define Episode_init_zero {false, {0, {0}}, false, "", false, 0, 0, {AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero, AudioFile_init_zero}, false, ImageGroup_init_zero} /* Field tags (for use in manual encoding/decoding) */ #define Artist_gid_tag 1 #define Artist_name_tag 2 +#define AudioFile_file_id_tag 1 +#define AudioFile_format_tag 2 #define Image_file_id_tag 1 -#define ImageGroup_image_tag 1 #define Restriction_countries_allowed_tag 2 #define Restriction_countries_forbidden_tag 3 +#define ImageGroup_image_tag 1 #define Album_gid_tag 1 #define Album_name_tag 2 #define Album_cover_group_tag 17 -#define AudioFile_file_id_tag 1 -#define AudioFile_format_tag 2 #define Episode_gid_tag 1 #define Episode_name_tag 2 #define Episode_duration_tag 7 @@ -140,52 +155,52 @@ extern "C" { /* Struct field encoding specification for nanopb */ #define AudioFile_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, BYTES, file_id, 1) \ +X(a, STATIC, OPTIONAL, BYTES, file_id, 1) \ X(a, STATIC, OPTIONAL, UENUM, format, 2) #define AudioFile_CALLBACK NULL #define AudioFile_DEFAULT NULL #define Restriction_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, STRING, countries_allowed, 2) \ -X(a, POINTER, OPTIONAL, STRING, countries_forbidden, 3) +X(a, STATIC, OPTIONAL, STRING, countries_allowed, 2) \ +X(a, STATIC, OPTIONAL, STRING, countries_forbidden, 3) #define Restriction_CALLBACK NULL #define Restriction_DEFAULT NULL #define Image_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, BYTES, file_id, 1) +X(a, STATIC, OPTIONAL, BYTES, file_id, 1) #define Image_CALLBACK NULL #define Image_DEFAULT NULL #define ImageGroup_FIELDLIST(X, a) \ -X(a, POINTER, REPEATED, MESSAGE, image, 1) +X(a, STATIC, REPEATED, MESSAGE, image, 1) #define ImageGroup_CALLBACK NULL #define ImageGroup_DEFAULT NULL #define ImageGroup_image_MSGTYPE Image #define Album_FIELDLIST(X, a) \ X(a, CALLBACK, OPTIONAL, BYTES, gid, 1) \ -X(a, POINTER, OPTIONAL, STRING, name, 2) \ +X(a, STATIC, OPTIONAL, STRING, name, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, cover_group, 17) #define Album_CALLBACK pb_default_field_callback #define Album_DEFAULT NULL #define Album_cover_group_MSGTYPE ImageGroup #define Artist_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ -X(a, POINTER, OPTIONAL, STRING, name, 2) +X(a, STATIC, OPTIONAL, BYTES, gid, 1) \ +X(a, STATIC, OPTIONAL, STRING, name, 2) #define Artist_CALLBACK NULL #define Artist_DEFAULT NULL #define Track_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ -X(a, POINTER, OPTIONAL, STRING, name, 2) \ +X(a, STATIC, OPTIONAL, BYTES, gid, 1) \ +X(a, STATIC, OPTIONAL, STRING, name, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, album, 3) \ -X(a, POINTER, REPEATED, MESSAGE, artist, 4) \ +X(a, STATIC, REPEATED, MESSAGE, artist, 4) \ X(a, STATIC, OPTIONAL, SINT32, duration, 7) \ -X(a, POINTER, REPEATED, MESSAGE, restriction, 11) \ -X(a, POINTER, REPEATED, MESSAGE, file, 12) \ -X(a, POINTER, REPEATED, MESSAGE, alternative, 13) -#define Track_CALLBACK NULL +X(a, CALLBACK, REPEATED, MESSAGE, restriction, 11) \ +X(a, STATIC, REPEATED, MESSAGE, file, 12) \ +X(a, CALLBACK, REPEATED, MESSAGE, alternative, 13) +#define Track_CALLBACK pb_default_field_callback #define Track_DEFAULT NULL #define Track_album_MSGTYPE Album #define Track_artist_MSGTYPE Artist @@ -194,11 +209,11 @@ X(a, POINTER, REPEATED, MESSAGE, alternative, 13) #define Track_alternative_MSGTYPE Track #define Episode_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ -X(a, POINTER, OPTIONAL, STRING, name, 2) \ +X(a, STATIC, OPTIONAL, BYTES, gid, 1) \ +X(a, STATIC, OPTIONAL, STRING, name, 2) \ X(a, STATIC, OPTIONAL, SINT32, duration, 7) \ -X(a, POINTER, REPEATED, MESSAGE, audio, 12) \ -X(a, POINTER, OPTIONAL, MESSAGE, covers, 68) +X(a, STATIC, REPEATED, MESSAGE, audio, 12) \ +X(a, STATIC, OPTIONAL, MESSAGE, covers, 68) #define Episode_CALLBACK NULL #define Episode_DEFAULT NULL #define Episode_audio_MSGTYPE AudioFile @@ -224,14 +239,14 @@ extern const pb_msgdesc_t Episode_msg; #define Episode_fields &Episode_msg /* Maximum encoded size of messages (where known) */ -/* AudioFile_size depends on runtime parameters */ -/* Restriction_size depends on runtime parameters */ -/* Image_size depends on runtime parameters */ -/* ImageGroup_size depends on runtime parameters */ /* Album_size depends on runtime parameters */ -/* Artist_size depends on runtime parameters */ /* Track_size depends on runtime parameters */ -/* Episode_size depends on runtime parameters */ +#define Artist_size 645 +#define AudioFile_size 133 +#define Episode_size 3290 +#define ImageGroup_size 1340 +#define Image_size 131 +#define Restriction_size 66 #ifdef __cplusplus } /* extern "C" */ diff --git a/components/spotify/cspot/protobuf/spirc.options b/components/spotify/cspot/protobuf/spirc.options index 5f853084..8684cadf 100644 --- a/components/spotify/cspot/protobuf/spirc.options +++ b/components/spotify/cspot/protobuf/spirc.options @@ -1,13 +1,12 @@ -Frame.ident type:FT_POINTER -Frame.protocol_version type:FT_POINTER -Frame.recipient type:FT_POINTER +Frame.ident max_size: 64, fixed_length:false +Frame.protocol_version max_size: 64, fixed_length:false +Frame.recipient max_count: 64, max_size: 64 Capability.stringValue max_count:50, max_size: 50 Capability.intValue max_count:50 -DeviceState.sw_version type:FT_POINTER -DeviceState.name type:FT_POINTER +DeviceState.sw_version max_size: 64, fixed_length:false +DeviceState.name max_size: 64, fixed_length:false DeviceState.capabilities max_count:17, fixed_count:false -State.context_uri type:FT_POINTER +State.context_uri max_size: 256, fixed_length:false State.track max_count:100, fixed_count:false -TrackRef.gid type:FT_POINTER -TrackRef.uri type:FT_POINTER -TrackRef.context type:FT_POINTER \ No newline at end of file +TrackRef.gid max_size: 128, fixed_length:false +TrackRef.uri max_size: 256 fixed_length:false diff --git a/components/spotify/cspot/protobuf/spirc.pb.c b/components/spotify/cspot/protobuf/spirc.pb.c index f6dfc4b1..99304244 100644 --- a/components/spotify/cspot/protobuf/spirc.pb.c +++ b/components/spotify/cspot/protobuf/spirc.pb.c @@ -6,7 +6,7 @@ #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(TrackRef, TrackRef, AUTO) +PB_BIND(TrackRef, TrackRef, 2) PB_BIND(State, State, 4) diff --git a/components/spotify/cspot/protobuf/spirc.pb.h b/components/spotify/cspot/protobuf/spirc.pb.h index 9ebc82b6..810fc6d3 100644 --- a/components/spotify/cspot/protobuf/spirc.pb.h +++ b/components/spotify/cspot/protobuf/spirc.pb.h @@ -62,23 +62,28 @@ typedef struct _Capability { char stringValue[50][50]; } Capability; +typedef PB_BYTES_ARRAY_T(128) TrackRef_gid_t; typedef struct _TrackRef { - pb_bytes_array_t *gid; - char *uri; + bool has_gid; + TrackRef_gid_t gid; + bool has_uri; + char uri[256]; bool has_queued; bool queued; - char *context; + pb_callback_t context; } TrackRef; typedef struct _DeviceState { - char *sw_version; + bool has_sw_version; + char sw_version[64]; bool has_is_active; bool is_active; bool has_can_play; bool can_play; bool has_volume; uint32_t volume; - char *name; + bool has_name; + char name[64]; bool has_error_code; uint32_t error_code; bool has_became_active_at; @@ -90,7 +95,8 @@ typedef struct _DeviceState { } DeviceState; typedef struct _State { - char *context_uri; + bool has_context_uri; + char context_uri[256]; bool has_index; uint32_t index; bool has_position_ms; @@ -113,8 +119,10 @@ typedef struct _State { typedef struct _Frame { bool has_version; uint32_t version; - char *ident; - char *protocol_version; + bool has_ident; + char ident[64]; + bool has_protocol_version; + char protocol_version[64]; bool has_seq_nr; uint32_t seq_nr; bool has_typ; @@ -130,7 +138,7 @@ typedef struct _Frame { bool has_state_update_id; int64_t state_update_id; pb_size_t recipient_count; - char **recipient; + char recipient[64][64]; } Frame; @@ -153,16 +161,16 @@ extern "C" { #endif /* Initializer values for message structs */ -#define TrackRef_init_default {NULL, NULL, false, 0, NULL} -#define State_init_default {NULL, false, 0, false, 0, false, _PlayStatus_MIN, false, 0, {{NULL}, NULL}, false, 0, false, 0, false, 0, 0, {TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default}} +#define TrackRef_init_default {false, {0, {0}}, false, "", false, 0, {{NULL}, NULL}} +#define State_init_default {false, "", false, 0, false, 0, false, _PlayStatus_MIN, false, 0, {{NULL}, NULL}, false, 0, false, 0, false, 0, 0, {TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default, TrackRef_init_default}} #define Capability_init_default {false, _CapabilityType_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}} -#define DeviceState_init_default {NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, 0, {{NULL}, NULL}, 0, {Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default}, {{NULL}, NULL}} -#define Frame_init_default {false, 0, NULL, NULL, false, 0, false, _MessageType_MIN, false, DeviceState_init_default, false, State_init_default, false, 0, false, 0, false, 0, 0, NULL} -#define TrackRef_init_zero {NULL, NULL, false, 0, NULL} -#define State_init_zero {NULL, false, 0, false, 0, false, _PlayStatus_MIN, false, 0, {{NULL}, NULL}, false, 0, false, 0, false, 0, 0, {TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero}} +#define DeviceState_init_default {false, "", false, 0, false, 0, false, 0, false, "", false, 0, false, 0, {{NULL}, NULL}, 0, {Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default, Capability_init_default}, {{NULL}, NULL}} +#define Frame_init_default {false, 0, false, "", false, "", false, 0, false, _MessageType_MIN, false, DeviceState_init_default, false, State_init_default, false, 0, false, 0, false, 0, 0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}} +#define TrackRef_init_zero {false, {0, {0}}, false, "", false, 0, {{NULL}, NULL}} +#define State_init_zero {false, "", false, 0, false, 0, false, _PlayStatus_MIN, false, 0, {{NULL}, NULL}, false, 0, false, 0, false, 0, 0, {TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero, TrackRef_init_zero}} #define Capability_init_zero {false, _CapabilityType_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}} -#define DeviceState_init_zero {NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, 0, {{NULL}, NULL}, 0, {Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero}, {{NULL}, NULL}} -#define Frame_init_zero {false, 0, NULL, NULL, false, 0, false, _MessageType_MIN, false, DeviceState_init_zero, false, State_init_zero, false, 0, false, 0, false, 0, 0, NULL} +#define DeviceState_init_zero {false, "", false, 0, false, 0, false, 0, false, "", false, 0, false, 0, {{NULL}, NULL}, 0, {Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero, Capability_init_zero}, {{NULL}, NULL}} +#define Frame_init_zero {false, 0, false, "", false, "", false, 0, false, _MessageType_MIN, false, DeviceState_init_zero, false, State_init_zero, false, 0, false, 0, false, 0, 0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}} /* Field tags (for use in manual encoding/decoding) */ #define Capability_typ_tag 1 @@ -206,15 +214,15 @@ extern "C" { /* Struct field encoding specification for nanopb */ #define TrackRef_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ -X(a, POINTER, OPTIONAL, STRING, uri, 2) \ +X(a, STATIC, OPTIONAL, BYTES, gid, 1) \ +X(a, STATIC, OPTIONAL, STRING, uri, 2) \ X(a, STATIC, OPTIONAL, BOOL, queued, 3) \ -X(a, POINTER, OPTIONAL, STRING, context, 4) -#define TrackRef_CALLBACK NULL +X(a, CALLBACK, OPTIONAL, STRING, context, 4) +#define TrackRef_CALLBACK pb_default_field_callback #define TrackRef_DEFAULT NULL #define State_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, STRING, context_uri, 2) \ +X(a, STATIC, OPTIONAL, STRING, context_uri, 2) \ X(a, STATIC, OPTIONAL, UINT32, index, 3) \ X(a, STATIC, OPTIONAL, UINT32, position_ms, 4) \ X(a, STATIC, OPTIONAL, UENUM, status, 5) \ @@ -236,11 +244,11 @@ X(a, STATIC, REPEATED, STRING, stringValue, 3) #define Capability_DEFAULT (const pb_byte_t*)"\x08\x01\x00" #define DeviceState_FIELDLIST(X, a) \ -X(a, POINTER, OPTIONAL, STRING, sw_version, 1) \ +X(a, STATIC, OPTIONAL, STRING, sw_version, 1) \ X(a, STATIC, OPTIONAL, BOOL, is_active, 10) \ X(a, STATIC, OPTIONAL, BOOL, can_play, 11) \ X(a, STATIC, OPTIONAL, UINT32, volume, 12) \ -X(a, POINTER, OPTIONAL, STRING, name, 13) \ +X(a, STATIC, OPTIONAL, STRING, name, 13) \ X(a, STATIC, OPTIONAL, UINT32, error_code, 14) \ X(a, STATIC, OPTIONAL, INT64, became_active_at, 15) \ X(a, CALLBACK, OPTIONAL, STRING, error_message, 16) \ @@ -252,8 +260,8 @@ X(a, CALLBACK, REPEATED, STRING, local_uris, 18) #define Frame_FIELDLIST(X, a) \ X(a, STATIC, OPTIONAL, UINT32, version, 1) \ -X(a, POINTER, OPTIONAL, STRING, ident, 2) \ -X(a, POINTER, OPTIONAL, STRING, protocol_version, 3) \ +X(a, STATIC, OPTIONAL, STRING, ident, 2) \ +X(a, STATIC, OPTIONAL, STRING, protocol_version, 3) \ X(a, STATIC, OPTIONAL, UINT32, seq_nr, 4) \ X(a, STATIC, OPTIONAL, UENUM, typ, 5) \ X(a, STATIC, OPTIONAL, MESSAGE, device_state, 7) \ @@ -261,7 +269,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, state, 12) \ X(a, STATIC, OPTIONAL, UINT32, position, 13) \ X(a, STATIC, OPTIONAL, UINT32, volume, 14) \ X(a, STATIC, OPTIONAL, INT64, state_update_id, 17) \ -X(a, POINTER, REPEATED, STRING, recipient, 18) +X(a, STATIC, REPEATED, STRING, recipient, 18) #define Frame_CALLBACK NULL #define Frame_DEFAULT (const pb_byte_t*)"\x28\x01\x00" #define Frame_device_state_MSGTYPE DeviceState diff --git a/components/spotify/cspot/src/MercuryManager.cpp b/components/spotify/cspot/src/MercuryManager.cpp index 62c842f3..36a3d9d3 100644 --- a/components/spotify/cspot/src/MercuryManager.cpp +++ b/components/spotify/cspot/src/MercuryManager.cpp @@ -11,7 +11,7 @@ std::map MercuryTypeMap({ MercuryManager::MercuryManager(std::unique_ptr session): bell::Task("mercuryManager", 6 * 1024, 2, 1) { - tempMercuryHeader = Header_init_default; + tempMercuryHeader = {}; this->timeProvider = std::make_shared(); this->callbacks = std::map(); this->subscriptions = std::map(); @@ -294,8 +294,11 @@ uint64_t MercuryManager::execute(MercuryType method, std::string uri, mercuryCal // Construct mercury header CSPOT_LOG(debug, "executing MercuryType %s", MercuryTypeMap[method].c_str()); - tempMercuryHeader.uri = (char *)(uri.c_str()); - tempMercuryHeader.method = (char *)(MercuryTypeMap[method].c_str()); + pbPutString(uri, tempMercuryHeader.uri); + pbPutString(MercuryTypeMap[method], tempMercuryHeader.method); + + tempMercuryHeader.has_method = true; + tempMercuryHeader.has_uri = true; // GET and SEND are actually the same. Therefore the override // The difference between them is only in header's method diff --git a/components/spotify/cspot/src/MercuryResponse.cpp b/components/spotify/cspot/src/MercuryResponse.cpp index 7026e98f..46dd8a48 100644 --- a/components/spotify/cspot/src/MercuryResponse.cpp +++ b/components/spotify/cspot/src/MercuryResponse.cpp @@ -3,13 +3,12 @@ MercuryResponse::MercuryResponse(std::vector &data) { // this->mercuryHeader = std::make_unique
(); - this->mercuryHeader = Header_init_default; + this->mercuryHeader = {}; this->parts = mercuryParts(0); this->parseResponse(data); } MercuryResponse::~MercuryResponse() { - pb_release(Header_fields, &mercuryHeader); } void MercuryResponse::parseResponse(std::vector &data) diff --git a/components/spotify/cspot/src/Packet.cpp b/components/spotify/cspot/src/Packet.cpp index 534e7cba..f7e0a503 100644 --- a/components/spotify/cspot/src/Packet.cpp +++ b/components/spotify/cspot/src/Packet.cpp @@ -1,6 +1,6 @@ #include "Packet.h" -Packet::Packet(uint8_t command, std::vector &data) { +Packet::Packet(uint8_t command, const std::vector &data) { this->command = command; this->data = data; }; \ No newline at end of file diff --git a/components/spotify/cspot/src/PlayerState.cpp b/components/spotify/cspot/src/PlayerState.cpp index 2b3f9aea..8e5066d9 100644 --- a/components/spotify/cspot/src/PlayerState.cpp +++ b/components/spotify/cspot/src/PlayerState.cpp @@ -24,7 +24,8 @@ PlayerState::PlayerState(std::shared_ptr timeProvider) innerFrame.state.repeat = false; innerFrame.state.has_repeat = true; - innerFrame.device_state.sw_version = (char*) swVersion; + innerFrame.device_state.has_sw_version = true; + pbPutCharArray(swVersion, innerFrame.device_state.sw_version); innerFrame.device_state.is_active = false; innerFrame.device_state.has_is_active = true; @@ -35,7 +36,8 @@ PlayerState::PlayerState(std::shared_ptr timeProvider) innerFrame.device_state.volume = configMan->volume; innerFrame.device_state.has_volume = true; - innerFrame.device_state.name = (char*) configMan->deviceName.c_str(); + innerFrame.device_state.has_name = true; + pbPutString(configMan->deviceName, innerFrame.device_state.name); // Prepare player's capabilities addCapability(CapabilityType_kCanBePlayer, 1); @@ -137,7 +139,8 @@ void PlayerState::updatePositionMs(uint32_t position) void PlayerState::updateTracks() { CSPOT_LOG(info, "---- Track count %d", remoteFrame.state.track_count); - innerFrame.state.context_uri = remoteFrame.state.context_uri == nullptr ? nullptr : strdup(remoteFrame.state.context_uri); + strcpy(innerFrame.state.context_uri, remoteFrame.state.context_uri); + std::copy(std::begin(remoteFrame.state.track), std::end(remoteFrame.state.track), std::begin(innerFrame.state.track)); innerFrame.state.track_count = remoteFrame.state.track_count; innerFrame.state.has_playing_track_index = true; @@ -198,9 +201,14 @@ std::vector PlayerState::encodeCurrentFrame(MessageType typ) { // Prepare current frame info innerFrame.version = 1; - innerFrame.ident = (char *) deviceId; + + pbPutCharArray(deviceId, innerFrame.ident); + innerFrame.has_ident = true; + innerFrame.seq_nr = this->seqNum; - innerFrame.protocol_version = (char*) protocolVersion; + pbPutCharArray(protocolVersion, innerFrame.protocol_version); + innerFrame.has_protocol_version = true; + innerFrame.typ = typ; innerFrame.state_update_id = timeProvider->getSyncedTimestamp(); innerFrame.has_version = true; diff --git a/components/spotify/cspot/src/Session.cpp b/components/spotify/cspot/src/Session.cpp index 4a51c4d9..638ef7f3 100644 --- a/components/spotify/cspot/src/Session.cpp +++ b/components/spotify/cspot/src/Session.cpp @@ -49,17 +49,26 @@ std::vector Session::authenticate(std::shared_ptr blob) authBlob = blob; // prepare authentication request proto - authRequest.login_credentials.username = (char *)(blob->username.c_str()); - authRequest.login_credentials.auth_data = vectorToPbArray(blob->authData); + pbPutString(blob->username, authRequest.login_credentials.username); + + std::copy(blob->authData.begin(), blob->authData.end(), authRequest.login_credentials.auth_data.bytes); + authRequest.login_credentials.auth_data.size = blob->authData.size(); + authRequest.login_credentials.typ = (AuthenticationType) blob->authType; authRequest.system_info.cpu_family = CpuFamily_CPU_UNKNOWN; authRequest.system_info.os = Os_OS_UNKNOWN; - authRequest.system_info.system_information_string = (char *)informationString; - authRequest.system_info.device_id = (char *)deviceId; - authRequest.version_string = (char *)versionString; + + auto infoStr = std::string(informationString); + pbPutString(infoStr, authRequest.system_info.system_information_string); + + auto deviceIdStr = std::string(deviceId); + pbPutString(deviceId, authRequest.system_info.device_id); + + auto versionStr = std::string(versionString); + pbPutString(versionStr, authRequest.version_string); + authRequest.has_version_string = true; auto data = pbEncode(ClientResponseEncrypted_fields, &authRequest); - free(authRequest.login_credentials.auth_data); // Send login request this->shanConn->sendPacket(LOGIN_REQUEST_COMMAND, data); diff --git a/components/spotify/cspot/src/SpotifyTrack.cpp b/components/spotify/cspot/src/SpotifyTrack.cpp index 6db0416c..e172bbd1 100644 --- a/components/spotify/cspot/src/SpotifyTrack.cpp +++ b/components/spotify/cspot/src/SpotifyTrack.cpp @@ -10,8 +10,8 @@ SpotifyTrack::SpotifyTrack(std::shared_ptr manager, std::shared_ { this->manager = manager; this->fileId = std::vector(); - episodeInfo = Episode_init_default; - trackInfo = Track_init_default; + episodeInfo = {}; + trackInfo = {}; mercuryCallback trackResponseLambda = [=](std::unique_ptr res) { this->trackInformationCallback(std::move(res), position_ms, isPaused); @@ -53,18 +53,18 @@ bool SpotifyTrack::countryListContains(std::string countryList, std::string coun bool SpotifyTrack::canPlayTrack() { - for (int x = 0; x < trackInfo.restriction_count; x++) - { - if (trackInfo.restriction[x].countries_allowed != nullptr) - { - return countryListContains(std::string(trackInfo.restriction[x].countries_allowed), manager->countryCode); - } - - if (trackInfo.restriction[x].countries_forbidden != nullptr) - { - return !countryListContains(std::string(trackInfo.restriction[x].countries_forbidden), manager->countryCode); - } - } +// for (int x = 0; x < trackInfo.restriction_count; x++) +// { +// if (strlen(trackInfo.restriction[x].countries_allowed) > 0) +// { +// return countryListContains(std::string(trackInfo.restriction[x].countries_allowed), manager->countryCode); +// } +// +// if (strlen(trackInfo.restriction[x].countries_forbidden) > 0) +// { +// return !countryListContains(std::string(trackInfo.restriction[x].countries_forbidden), manager->countryCode); +// } +// } return true; } @@ -77,35 +77,39 @@ void SpotifyTrack::trackInformationCallback(std::unique_ptr res pb_release(Track_fields, &trackInfo); pbDecode(trackInfo, Track_fields, response->parts[0]); +// +// CSPOT_LOG(info, "Track name: %s", trackInfo.name); +// CSPOT_LOG(info, "Track duration: %d", trackInfo.duration); +// CSPOT_LOG(debug, "trackInfo.restriction.size() = %d", trackInfo.restriction_count); +// int altIndex = 0; +// while (!canPlayTrack()) +// { +// auto src = trackInfo.alternative[altIndex].restriction; +//// std::copy(std::begin(src), std::end(src), std::begin(trackInfo.restriction)); +//// trackInfo.restriction_count = trackInfo.alternative[altIndex].restriction_count; +//// +//// free(trackInfo.gid); +// trackInfo.gid = trackInfo.alternative[altIndex].gid; +// altIndex++; +// CSPOT_LOG(info, "Trying alternative %d", altIndex); +// } - CSPOT_LOG(info, "Track name: %s", trackInfo.name); - CSPOT_LOG(info, "Track duration: %d", trackInfo.duration); - CSPOT_LOG(debug, "trackInfo.restriction.size() = %d", trackInfo.restriction_count); - int altIndex = 0; - while (!canPlayTrack()) - { - trackInfo.restriction = trackInfo.alternative[altIndex].restriction; - trackInfo.restriction_count = trackInfo.alternative[altIndex].restriction_count; - trackInfo.gid = trackInfo.alternative[altIndex].gid; - trackInfo.file = trackInfo.alternative[altIndex].file; - altIndex++; - CSPOT_LOG(info, "Trying alternative %d", altIndex); - } - auto trackId = pbArrayToVector(trackInfo.gid); + auto trackId = std::vector(trackInfo.gid.bytes, trackInfo.gid.bytes + trackInfo.gid.size); this->fileId = std::vector(); for (int x = 0; x < trackInfo.file_count; x++) { if (trackInfo.file[x].format == configMan->format) { - this->fileId = pbArrayToVector(trackInfo.file[x].file_id); + this->fileId = std::vector(trackInfo.file[x].file_id.bytes, trackInfo.file[x].file_id.bytes + trackInfo.file[x].file_id.size); break; // If file found stop searching } } if (trackInfoReceived != nullptr) { - auto imageId = pbArrayToVector(trackInfo.album.cover_group.image[0].file_id); + auto imageIdBytes = trackInfo.album.cover_group.image[0].file_id; + auto imageId = std::vector(imageIdBytes.bytes, imageIdBytes.bytes + imageIdBytes.size); TrackInfo simpleTrackInfo = { .name = std::string(trackInfo.name), .album = std::string(trackInfo.album.name), @@ -139,14 +143,15 @@ void SpotifyTrack::episodeInformationCallback(std::unique_ptr r { if (episodeInfo.audio[x].format == AudioFormat_OGG_VORBIS_96) { - this->fileId = pbArrayToVector(episodeInfo.audio[x].file_id); + this->fileId = std::vector(episodeInfo.audio[x].file_id.bytes, episodeInfo.audio[x].file_id.bytes + episodeInfo.audio[x].file_id.size); break; // If file found stop searching } } if (trackInfoReceived != nullptr) { - auto imageId = pbArrayToVector(episodeInfo.covers->image[0].file_id); + auto imageFileId = episodeInfo.covers.image[0].file_id; + auto imageId = std::vector(imageFileId.bytes, imageFileId.bytes + imageFileId.size); TrackInfo simpleTrackInfo = { .name = std::string(episodeInfo.name), .album = "", @@ -159,7 +164,7 @@ void SpotifyTrack::episodeInformationCallback(std::unique_ptr r trackInfoReceived(simpleTrackInfo); } - this->requestAudioKey(pbArrayToVector(episodeInfo.gid), this->fileId, episodeInfo.duration, position_ms, isPaused); + this->requestAudioKey(std::vector(episodeInfo.gid.bytes, episodeInfo.gid.bytes + episodeInfo.gid.size), this->fileId, episodeInfo.duration, position_ms, isPaused); } void SpotifyTrack::requestAudioKey(std::vector fileId, std::vector trackId, int32_t trackDuration, uint32_t position_ms, bool isPaused) diff --git a/components/spotify/cspot/src/TrackReference.cpp b/components/spotify/cspot/src/TrackReference.cpp index e51afb35..a165c39a 100644 --- a/components/spotify/cspot/src/TrackReference.cpp +++ b/components/spotify/cspot/src/TrackReference.cpp @@ -3,11 +3,11 @@ TrackReference::TrackReference(TrackRef *ref) { - if (ref->gid != nullptr) + if (ref->gid.size > 0) { - gid = pbArrayToVector(ref->gid); + gid = std::vector(ref->gid.bytes, ref->gid.bytes + ref->gid.size); } - else if (ref->uri != nullptr) + else if (strlen(ref->uri) > 0) { auto uri = std::string(ref->uri); auto idString = uri.substr(uri.find_last_of(":") + 1, uri.size()); diff --git a/components/spotify/cspot_sink.c b/components/spotify/cspot_sink.c index 0df72605..bf6343dc 100644 --- a/components/spotify/cspot_sink.c +++ b/components/spotify/cspot_sink.c @@ -106,7 +106,7 @@ static bool cmd_handler(cspot_event_t event, ...) { switch(event) { case CSPOT_SETUP: actrls_set(controls, false, NULL, actrls_ir_action); - displayer_control(DISPLAYER_ACTIVATE, "SPOTIFY"); + displayer_control(DISPLAYER_ACTIVATE, "SPOTIFY", false); break; case CSPOT_PLAY: displayer_control(DISPLAYER_TIMER_RUN);