airplay artwork and CSpot leak fix (temporary)

This commit is contained in:
Philippe G
2022-01-09 19:40:18 -08:00
parent e9da432bfc
commit 3125a095fa
43 changed files with 396 additions and 271 deletions

View File

@@ -2,6 +2,7 @@ idf_component_register(SRC_DIRS . core core/ifaces fonts
INCLUDE_DIRS . fonts core INCLUDE_DIRS . fonts core
REQUIRES platform_config tools esp_common REQUIRES platform_config tools esp_common
PRIV_REQUIRES services freertos driver PRIV_REQUIRES services freertos driver
EMBED_FILES note.jpg
) )
set_source_files_properties(display.c set_source_files_properties(display.c

View File

@@ -86,7 +86,7 @@ static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
Device->WriteCommand( Device, 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); *CS_post = Speed / (8*1000*1000);
} }

View File

@@ -238,9 +238,10 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
void GDS_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { if (Device->SetLayout) Device->SetLayout( Device, HFlip, VFlip, Rotate ); } 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; } void GDS_SetDirty( struct GDS_Device* Device ) { Device->Dirty = true; }
int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; } int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; }
int GDS_GetHeight( struct GDS_Device* Device ) { return Device ? Device->Height : 0; } void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; }
int GDS_GetDepth( struct GDS_Device* Device ) { return Device ? Device->Depth : 0; } int GDS_GetHeight( struct GDS_Device* Device ) { return Device ? Device->Height : 0; }
int GDS_GetMode( struct GDS_Device* Device ) { return Device ? Device->Mode : 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_DisplayOn( struct GDS_Device* Device ) { if (Device->DisplayOn) Device->DisplayOn( Device ); }
void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device->DisplayOff) Device->DisplayOff( Device ); } void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device->DisplayOff) Device->DisplayOff( Device ); }

View File

@@ -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_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate );
void GDS_SetDirty( struct GDS_Device* Device ); void GDS_SetDirty( struct GDS_Device* Device );
int GDS_GetWidth( 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_GetHeight( struct GDS_Device* Device );
int GDS_GetDepth( struct GDS_Device* Device ); int GDS_GetDepth( struct GDS_Device* Device );
int GDS_GetMode( struct GDS_Device* Device ); int GDS_GetMode( struct GDS_Device* Device );

View File

@@ -73,13 +73,13 @@ void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y,
CharStartY+= OffsetY; CharStartY+= OffsetY;
/* Do not attempt to draw if this character is entirely offscreen */ /* 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 ); ClipDebug( x, y );
return; return;
} }
/* Do not attempt to draw past the end of the screen */ /* 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; CharEndY = ( CharEndY >= Device->Height ) ? Device->Height - 1 : CharEndY;
Device->Dirty = true; Device->Dirty = true;
@@ -146,7 +146,7 @@ int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character ) {
} }
int GDS_FontGetMaxCharsPerRow( struct GDS_Device* Display ) { 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 ) { int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display ) {
@@ -210,7 +210,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
switch ( Anchor ) { switch ( Anchor ) {
case TextAnchor_East: { case TextAnchor_East: {
*OutY = ( Display->Height / 2 ) - ( StringHeight / 2 ); *OutY = ( Display->Height / 2 ) - ( StringHeight / 2 );
*OutX = ( Display->Width - StringWidth ); *OutX = ( Display->TextWidth - StringWidth );
break; break;
} }
@@ -221,19 +221,19 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
break; break;
} }
case TextAnchor_North: { case TextAnchor_North: {
*OutX = ( Display->Width / 2 ) - ( StringWidth / 2 ); *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 );
*OutY = 0; *OutY = 0;
break; break;
} }
case TextAnchor_South: { case TextAnchor_South: {
*OutX = ( Display->Width / 2 ) - ( StringWidth / 2 ); *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 );
*OutY = ( Display->Height - StringHeight ); *OutY = ( Display->Height - StringHeight );
break; break;
} }
case TextAnchor_NorthEast: { case TextAnchor_NorthEast: {
*OutX = ( Display->Width - StringWidth ); *OutX = ( Display->TextWidth - StringWidth );
*OutY = 0; *OutY = 0;
break; break;
@@ -246,7 +246,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
} }
case TextAnchor_SouthEast: { case TextAnchor_SouthEast: {
*OutY = ( Display->Height - StringHeight ); *OutY = ( Display->Height - StringHeight );
*OutX = ( Display->Width - StringWidth ); *OutX = ( Display->TextWidth - StringWidth );
break; break;
} }
@@ -258,7 +258,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
} }
case TextAnchor_Center: { case TextAnchor_Center: {
*OutY = ( Display->Height / 2 ) - ( StringHeight / 2 ); *OutY = ( Display->Height / 2 ) - ( StringHeight / 2 );
*OutX = ( Display->Width / 2 ) - ( StringWidth / 2 ); *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 );
break; break;
} }

View File

@@ -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) { static void* DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, bool SizeOnly, int RGB_Mode) {
JDEC Decoder; JDEC Decoder;
JpegCtx Context; JpegCtx Context;
char *Scratch = calloc(SCRATCH_SIZE, 1); char *Scratch = malloc(SCRATCH_SIZE);
if (!Scratch) { if (!Scratch) {
ESP_LOGE(TAG, "Cannot allocate workspace"); 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; JDEC Decoder;
JpegCtx Context; JpegCtx Context;
bool Ret = false; bool Ret = false;
char *Scratch = calloc(SCRATCH_SIZE, 1); char *Scratch = malloc(SCRATCH_SIZE);
if (!Scratch) { if (!Scratch) {
ESP_LOGE(TAG, "Cannot allocate workspace"); ESP_LOGE(TAG, "Cannot allocate workspace");

View File

@@ -95,7 +95,7 @@ struct GDS_Device {
const struct GDS_FontDef* Font; const struct GDS_FontDef* Font;
} Lines[MAX_LINES]; } Lines[MAX_LINES];
uint16_t Width; uint16_t Width, TextWidth;
uint16_t Height; uint16_t Height;
uint8_t Depth, Mode; 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 (*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 ); void (*ClearWindow)( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color );
// may provide for tweaking // 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 // interface-specific methods
WriteCommandProc WriteCommand; WriteCommandProc WriteCommand;

View File

@@ -100,13 +100,13 @@ bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Tex
Width = GDS_FontMeasureString( Device, Text ); Width = GDS_FontMeasureString( Device, Text );
// adjusting position, erase only EoL for rigth-justified // adjusting position, erase only EoL for rigth-justified
if (Pos == GDS_TEXT_RIGHT) X = Device->Width - Width - 1; if (Pos == GDS_TEXT_RIGHT) X = Device->TextWidth - Width - 1;
else if (Pos == GDS_TEXT_CENTER) X = (Device->Width - Width) / 2; else if (Pos == GDS_TEXT_CENTER) X = (Device->TextWidth - Width) / 2;
// erase if requested // erase if requested
if (Attr & GDS_TEXT_CLEAR) { 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); 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++) for (int y = Y_min; y < Y_max; y++)
DrawPixelFast( Device, c, y, GDS_COLOR_BLACK ); 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; Device->Dirty = true;
if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device ); 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 // we might already fit
GDS_SetFont( Device, Device->Lines[N].Font ); 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 // add some space for better visual
strncat(String, Space, Max-Len); 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 ); Boundary = GDS_FontMeasureString( Device, String );
// add a full display width // 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++] = String[Extra++];
String[Len] = '\0'; String[Len] = '\0';
} }

View File

@@ -75,7 +75,7 @@ bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int
Device->RSTPin = RSTPin; Device->RSTPin = RSTPin;
Device->Backlight.Pin = BacklightPin; Device->Backlight.Pin = BacklightPin;
Device->IF = GDS_IF_I2C; Device->IF = GDS_IF_I2C;
Device->Width = Width; Device->Width = Device->TextWidth = Width;
Device->Height = Height; Device->Height = Height;
if ( RSTPin >= 0 ) { if ( RSTPin >= 0 ) {

View File

@@ -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 ) { 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; spi_device_handle_t SPIDevice;
NullCheck( Device, return false ); 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 ); 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.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M;
SPIDeviceConfig.spics_io_num = CSPin; SPIDeviceConfig.spics_io_num = CSPin;
SPIDeviceConfig.queue_size = 1; SPIDeviceConfig.queue_size = 1;
@@ -63,7 +61,7 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
Device->CSPin = CSPin; Device->CSPin = CSPin;
Device->Backlight.Pin = BackLightPin; Device->Backlight.Pin = BackLightPin;
Device->IF = GDS_IF_SPI; Device->IF = GDS_IF_SPI;
Device->Width = Width; Device->Width = Device->TextWidth = Width;
Device->Height = Height; Device->Height = Height;
if ( RSTPin >= 0 ) { if ( RSTPin >= 0 ) {

View File

@@ -20,6 +20,7 @@
#include "gds_draw.h" #include "gds_draw.h"
#include "gds_text.h" #include "gds_text.h"
#include "gds_font.h" #include "gds_font.h"
#include "gds_image.h"
static const char *TAG = "display"; static const char *TAG = "display";
@@ -30,6 +31,9 @@ static const char *TAG = "display";
#define SCROLLABLE_SIZE 384 #define SCROLLABLE_SIZE 384
#define HEADER_SIZE 64 #define HEADER_SIZE 64
#define DEFAULT_SLEEP 3600 #define DEFAULT_SLEEP 3600
#define ARTWORK_BORDER 1
extern const uint8_t default_artwork[] asm("_binary_note_jpg_start");
static EXT_RAM_ATTR struct { static EXT_RAM_ATTR struct {
TaskHandle_t task; TaskHandle_t task;
@@ -47,6 +51,12 @@ static EXT_RAM_ATTR struct {
char string[8]; // H:MM:SS char string[8]; // H:MM:SS
bool visible; bool visible;
} duration; } duration;
struct {
bool enable, fit;
bool updated;
int tick;
int offset;
} artwork;
TickType_t tick; TickType_t tick;
} displayer; } displayer;
@@ -147,6 +157,14 @@ void display_init(char *welcome) {
GDS_TextSetFontAuto(display, 2, GDS_FONT_LINE_2, -3); GDS_TextSetFontAuto(display, 2, GDS_FONT_LINE_2, -3);
displayer.metadata_config = config_alloc_get(NVS_TYPE_STR, "metadata_config"); 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); free(config);
@@ -226,6 +244,11 @@ static void displayer_task(void *args) {
GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, displayer.header); GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, displayer.header);
GDS_TextLine(display, 1, GDS_TEXT_RIGHT, GDS_TEXT_UPDATE, _line); 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; timer_sleep = 1000;
} else timer_sleep = max(1000 - elapsed, 0); } else timer_sleep = max(1000 - elapsed, 0);
} else timer_sleep = DEFAULT_SLEEP; } 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) { switch(cmd) {
case DISPLAYER_ACTIVATE: { case DISPLAYER_ACTIVATE: {
char *header = va_arg(args, char*); char *header = va_arg(args, char*);
bool artwork = va_arg(args, int);
strncpy(displayer.header, header, HEADER_SIZE); strncpy(displayer.header, header, HEADER_SIZE);
displayer.header[HEADER_SIZE] = '\0'; displayer.header[HEADER_SIZE] = '\0';
displayer.state = DISPLAYER_ACTIVE; displayer.state = DISPLAYER_ACTIVE;
@@ -388,6 +431,7 @@ void displayer_control(enum displayer_cmd_e cmd, ...) {
displayer.duration.visible = false; displayer.duration.visible = false;
displayer.offset = displayer.boundary = 0; displayer.offset = displayer.boundary = 0;
display_bus(&displayer, DISPLAY_BUS_TAKE); display_bus(&displayer, DISPLAY_BUS_TAKE);
if (artwork) GDS_SetTextWidth(display, displayer.artwork.offset);
vTaskResume(displayer.task); vTaskResume(displayer.task);
break; break;
} }
@@ -398,6 +442,8 @@ void displayer_control(enum displayer_cmd_e cmd, ...) {
break; break;
case DISPLAYER_SHUTDOWN: case DISPLAYER_SHUTDOWN:
// let the task self-suspend (we might be doing i2c_write) // 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; displayer.state = DISPLAYER_DOWN;
display_bus(&displayer, DISPLAY_BUS_GIVE); display_bus(&displayer, DISPLAY_BUS_GIVE);
break; break;

View File

@@ -38,5 +38,6 @@ bool display_is_valid_driver(const char * driver);
void displayer_scroll(char *string, int speed, int pause); void displayer_scroll(char *string, int speed, int pause);
void displayer_control(enum displayer_cmd_e cmd, ...); void displayer_control(enum displayer_cmd_e cmd, ...);
void displayer_metadata(char *artist, char *album, char *title); 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); void displayer_timer(enum displayer_time_e mode, int elapsed, int duration);
char * display_get_supported_drivers(void); char * display_get_supported_drivers(void);

BIN
components/display/note.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -172,7 +172,7 @@ static bool cmd_handler(bt_sink_cmd_t cmd, ...) {
// now handle events for display // now handle events for display
switch(cmd) { switch(cmd) {
case BT_SINK_AUDIO_STARTED: case BT_SINK_AUDIO_STARTED:
displayer_control(DISPLAYER_ACTIVATE, "BLUETOOTH"); displayer_control(DISPLAYER_ACTIVATE, "BLUETOOTH", false);
break; break;
case BT_SINK_AUDIO_STOPPED: case BT_SINK_AUDIO_STOPPED:
displayer_control(DISPLAYER_SUSPEND); displayer_control(DISPLAYER_SUSPEND);

View File

@@ -628,6 +628,9 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
LOG_INFO("[%p]: received metadata", ctx); LOG_INFO("[%p]: received metadata", ctx);
settings.ctx = &metadata; settings.ctx = &metadata;
memset(&metadata, 0, sizeof(struct metadata_s)); memset(&metadata, 0, sizeof(struct metadata_s));
if (!dmap_parse(&settings, body, len)) {
LOG_INFO("[%p]: received metadata\n\tartist: %s\n\talbum: %s\n\ttitle: %s",
ctx, metadata.artist, metadata.album, metadata.title);
success = ctx->cmd_cb(RAOP_METADATA, metadata.artist, metadata.album, metadata.title); success = ctx->cmd_cb(RAOP_METADATA, metadata.artist, metadata.album, metadata.title);
free_metadata(&metadata); free_metadata(&metadata);
} }

View File

@@ -112,7 +112,7 @@ static bool cmd_handler(raop_event_t event, ...) {
switch(event) { switch(event) {
case RAOP_SETUP: case RAOP_SETUP:
actrls_set(controls, false, NULL, actrls_ir_action); actrls_set(controls, false, NULL, actrls_ir_action);
displayer_control(DISPLAYER_ACTIVATE, "AIRPLAY"); displayer_control(DISPLAYER_ACTIVATE, "AIRPLAY", true);
break; break;
case RAOP_PLAY: case RAOP_PLAY:
displayer_control(DISPLAYER_TIMER_RUN); displayer_control(DISPLAYER_TIMER_RUN);
@@ -127,6 +127,12 @@ static bool cmd_handler(raop_event_t event, ...) {
case RAOP_METADATA: { case RAOP_METADATA: {
char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*); char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*);
displayer_metadata(artist, album, title); displayer_metadata(artist, album, title);
displayer_artwork(NULL);
break;
}
case RAOP_ARTWORK: {
uint8_t *data = va_arg(args, uint8_t*);
displayer_artwork(data);
break; break;
} }
case RAOP_PROGRESS: { case RAOP_PROGRESS: {

View File

@@ -14,7 +14,7 @@
#define RAOP_SAMPLE_RATE 44100 #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, RAOP_TIMING, RAOP_PREV, RAOP_NEXT, RAOP_REW, RAOP_FWD,
RAOP_VOLUME_UP, RAOP_VOLUME_DOWN, RAOP_RESUME, RAOP_TOGGLE } raop_event_t ; RAOP_VOLUME_UP, RAOP_VOLUME_DOWN, RAOP_RESUME, RAOP_TOGGLE } raop_event_t ;

View File

@@ -120,7 +120,8 @@ static void cspotTask(void *pvParameters) {
case CSpotEventType::TRACK_INFO: { case CSpotEventType::TRACK_INFO: {
TrackInfo track = std::get<TrackInfo>(event.data); TrackInfo track = std::get<TrackInfo>(event.data);
// duration is in chunks of 0.5 ms // 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; break;
} }
case CSpotEventType::PLAY_PAUSE: { case CSpotEventType::PLAY_PAUSE: {

View File

@@ -45,5 +45,6 @@ endif()
add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS}) add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS})
# PUBLIC to propagate includes from bell to cspot dependents # PUBLIC to propagate includes from bell to cspot dependents
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC) target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
target_compile_definitions(bell PUBLIC PB_FIELD_32BIT)
target_link_libraries(cspot PUBLIC ${EXTRA_LIBS}) target_link_libraries(cspot PUBLIC ${EXTRA_LIBS})
target_include_directories(cspot PUBLIC "include" ${GENERATED_INCLUDES} ${NANOPB_INCLUDE_DIRS}) target_include_directories(cspot PUBLIC "include" ${GENERATED_INCLUDES} ${NANOPB_INCLUDE_DIRS})

View File

@@ -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_CJSON "" CACHE STRING "External cJSON library target name, optional")
#set(BELL_EXTERNAL_TREMOR "" CACHE STRING "External tremor library target name, optional") #set(BELL_EXTERNAL_TREMOR "" CACHE STRING "External tremor library target name, optional")
add_definitions(-DPB_ENABLE_MALLOC)
# Include nanoPB library # Include nanoPB library
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra)
find_package(Nanopb REQUIRED) find_package(Nanopb REQUIRED)
@@ -98,3 +96,4 @@ message(${NANOPB_INCLUDE_DIRS})
# PUBLIC to propagate esp-idf includes to bell dependents # PUBLIC to propagate esp-idf includes to bell dependents
target_link_libraries(bell PUBLIC ${EXTRA_LIBS}) target_link_libraries(bell PUBLIC ${EXTRA_LIBS})
target_include_directories(bell PUBLIC "include" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(bell PUBLIC "include" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)

View File

@@ -42,6 +42,10 @@ void pbDecode(T &result, const pb_msgdesc_t *fields, std::vector<uint8_t> &data)
} }
} }
void pbPutString(const std::string &stringToPack, char* dst);
void pbPutCharArray(const char * stringToPack, char* dst);
void pbPutBytes(const std::vector<uint8_t> &data, pb_bytes_array_t &dst);
const char* pb_encode_to_string(const pb_msgdesc_t *fields, const void *data); 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); pb_istream_t pb_istream_from_http(bell::HTTPClient::HTTPResponse *response, size_t length = 0);

View File

@@ -47,6 +47,22 @@ pb_bytes_array_t* vectorToPbArray(const std::vector<uint8_t>& vectorToPack)
return result; 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<uint8_t> &data, pb_bytes_array_t &dst) {
dst.size = data.size();
std::copy(data.begin(), data.end(), dst.bytes);
}
std::vector<uint8_t> pbArrayToVector(pb_bytes_array_t* pbArray) { std::vector<uint8_t> pbArrayToVector(pb_bytes_array_t* pbArray) {
return std::vector<uint8_t>(pbArray->bytes, pbArray->bytes + pbArray->size); return std::vector<uint8_t>(pbArray->bytes, pbArray->bytes + pbArray->size);
} }

View File

@@ -9,7 +9,7 @@ class Packet
private: private:
public: public:
Packet(uint8_t command, std::vector<uint8_t> &data); Packet(uint8_t command, const std::vector<uint8_t> &data);
uint8_t command; uint8_t command;
std::vector<uint8_t> data; std::vector<uint8_t> data;
}; };

View File

@@ -1,6 +1,5 @@
LoginCredentials.username type:FT_POINTER LoginCredentials.username max_size:30, fixed_length:false
LoginCredentials.auth_data type:FT_POINTER LoginCredentials.auth_data max_size:512, fixed_length:false
LoginCredentials.auth_data type:FT_POINTER SystemInfo.system_information_string max_size:16, fixed_length:false
SystemInfo.system_information_string type:FT_POINTER SystemInfo.device_id max_size:50, fixed_length:false
SystemInfo.device_id type:FT_POINTER ClientResponseEncrypted.version_string max_size:32, fixed_length:false
ClientResponseEncrypted.version_string type:FT_POINTER

View File

@@ -9,7 +9,7 @@
PB_BIND(SystemInfo, SystemInfo, 2) PB_BIND(SystemInfo, SystemInfo, 2)
PB_BIND(LoginCredentials, LoginCredentials, AUTO) PB_BIND(LoginCredentials, LoginCredentials, 2)
PB_BIND(ClientResponseEncrypted, ClientResponseEncrypted, 2) PB_BIND(ClientResponseEncrypted, ClientResponseEncrypted, 2)

View File

@@ -58,23 +58,25 @@ typedef enum _AuthenticationType {
} AuthenticationType; } AuthenticationType;
/* Struct definitions */ /* Struct definitions */
typedef PB_BYTES_ARRAY_T(512) LoginCredentials_auth_data_t;
typedef struct _LoginCredentials { typedef struct _LoginCredentials {
char *username; char username[30];
AuthenticationType typ; AuthenticationType typ;
pb_bytes_array_t *auth_data; LoginCredentials_auth_data_t auth_data;
} LoginCredentials; } LoginCredentials;
typedef struct _SystemInfo { typedef struct _SystemInfo {
CpuFamily cpu_family; CpuFamily cpu_family;
Os os; Os os;
char *system_information_string; char system_information_string[16];
char *device_id; char device_id[50];
} SystemInfo; } SystemInfo;
typedef struct _ClientResponseEncrypted { typedef struct _ClientResponseEncrypted {
LoginCredentials login_credentials; LoginCredentials login_credentials;
SystemInfo system_info; SystemInfo system_info;
char *version_string; bool has_version_string;
char version_string[32];
} ClientResponseEncrypted; } ClientResponseEncrypted;
@@ -97,12 +99,12 @@ extern "C" {
#endif #endif
/* Initializer values for message structs */ /* Initializer values for message structs */
#define SystemInfo_init_default {_CpuFamily_MIN, _Os_MIN, NULL, NULL} #define SystemInfo_init_default {_CpuFamily_MIN, _Os_MIN, "", ""}
#define LoginCredentials_init_default {NULL, _AuthenticationType_MIN, NULL} #define LoginCredentials_init_default {"", _AuthenticationType_MIN, {0, {0}}}
#define ClientResponseEncrypted_init_default {LoginCredentials_init_default, SystemInfo_init_default, NULL} #define ClientResponseEncrypted_init_default {LoginCredentials_init_default, SystemInfo_init_default, false, ""}
#define SystemInfo_init_zero {_CpuFamily_MIN, _Os_MIN, NULL, NULL} #define SystemInfo_init_zero {_CpuFamily_MIN, _Os_MIN, "", ""}
#define LoginCredentials_init_zero {NULL, _AuthenticationType_MIN, NULL} #define LoginCredentials_init_zero {"", _AuthenticationType_MIN, {0, {0}}}
#define ClientResponseEncrypted_init_zero {LoginCredentials_init_zero, SystemInfo_init_zero, NULL} #define ClientResponseEncrypted_init_zero {LoginCredentials_init_zero, SystemInfo_init_zero, false, ""}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
#define LoginCredentials_username_tag 10 #define LoginCredentials_username_tag 10
@@ -120,22 +122,22 @@ extern "C" {
#define SystemInfo_FIELDLIST(X, a) \ #define SystemInfo_FIELDLIST(X, a) \
X(a, STATIC, REQUIRED, UENUM, cpu_family, 10) \ X(a, STATIC, REQUIRED, UENUM, cpu_family, 10) \
X(a, STATIC, REQUIRED, UENUM, os, 60) \ X(a, STATIC, REQUIRED, UENUM, os, 60) \
X(a, POINTER, OPTIONAL, STRING, system_information_string, 90) \ X(a, STATIC, REQUIRED, STRING, system_information_string, 90) \
X(a, POINTER, OPTIONAL, STRING, device_id, 100) X(a, STATIC, REQUIRED, STRING, device_id, 100)
#define SystemInfo_CALLBACK NULL #define SystemInfo_CALLBACK NULL
#define SystemInfo_DEFAULT NULL #define SystemInfo_DEFAULT NULL
#define LoginCredentials_FIELDLIST(X, a) \ #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, 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_CALLBACK NULL
#define LoginCredentials_DEFAULT NULL #define LoginCredentials_DEFAULT NULL
#define ClientResponseEncrypted_FIELDLIST(X, a) \ #define ClientResponseEncrypted_FIELDLIST(X, a) \
X(a, STATIC, REQUIRED, MESSAGE, login_credentials, 10) \ X(a, STATIC, REQUIRED, MESSAGE, login_credentials, 10) \
X(a, STATIC, REQUIRED, MESSAGE, system_info, 50) \ 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_CALLBACK NULL
#define ClientResponseEncrypted_DEFAULT NULL #define ClientResponseEncrypted_DEFAULT NULL
#define ClientResponseEncrypted_login_credentials_MSGTYPE LoginCredentials #define ClientResponseEncrypted_login_credentials_MSGTYPE LoginCredentials
@@ -151,9 +153,9 @@ extern const pb_msgdesc_t ClientResponseEncrypted_msg;
#define ClientResponseEncrypted_fields &ClientResponseEncrypted_msg #define ClientResponseEncrypted_fields &ClientResponseEncrypted_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
/* SystemInfo_size depends on runtime parameters */ #define ClientResponseEncrypted_size 665
/* LoginCredentials_size depends on runtime parameters */ #define LoginCredentials_size 550
/* ClientResponseEncrypted_size depends on runtime parameters */ #define SystemInfo_size 75
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -48,14 +48,14 @@ enum AuthenticationType {
message SystemInfo { message SystemInfo {
required CpuFamily cpu_family = 0xa; required CpuFamily cpu_family = 0xa;
required Os os = 0x3c; required Os os = 0x3c;
optional string system_information_string = 0x5a; required string system_information_string = 0x5a;
optional string device_id = 0x64; required string device_id = 0x64;
} }
message LoginCredentials { message LoginCredentials {
optional string username = 0xa; required string username = 0xa;
required AuthenticationType typ = 0x14; required AuthenticationType typ = 0x14;
optional bytes auth_data = 0x1e; required bytes auth_data = 0x1e;
} }
message ClientResponseEncrypted { message ClientResponseEncrypted {

View File

@@ -1,2 +1,2 @@
Header.uri type:FT_POINTER Header.uri max_size:64, fixed_length:false
Header.method type:FT_POINTER Header.method max_size:32, fixed_length:false

View File

@@ -11,8 +11,10 @@
/* Struct definitions */ /* Struct definitions */
typedef struct _Header { typedef struct _Header {
char *uri; bool has_uri;
char *method; char uri[64];
bool has_method;
char method[32];
} Header; } Header;
@@ -21,8 +23,8 @@ extern "C" {
#endif #endif
/* Initializer values for message structs */ /* Initializer values for message structs */
#define Header_init_default {NULL, NULL} #define Header_init_default {false, "", false, ""}
#define Header_init_zero {NULL, NULL} #define Header_init_zero {false, "", false, ""}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
#define Header_uri_tag 1 #define Header_uri_tag 1
@@ -30,8 +32,8 @@ extern "C" {
/* Struct field encoding specification for nanopb */ /* Struct field encoding specification for nanopb */
#define Header_FIELDLIST(X, a) \ #define Header_FIELDLIST(X, a) \
X(a, POINTER, OPTIONAL, STRING, uri, 1) \ X(a, STATIC, OPTIONAL, STRING, uri, 1) \
X(a, POINTER, OPTIONAL, STRING, method, 3) X(a, STATIC, OPTIONAL, STRING, method, 3)
#define Header_CALLBACK NULL #define Header_CALLBACK NULL
#define Header_DEFAULT NULL #define Header_DEFAULT NULL
@@ -41,7 +43,7 @@ extern const pb_msgdesc_t Header_msg;
#define Header_fields &Header_msg #define Header_fields &Header_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
/* Header_size depends on runtime parameters */ #define Header_size 98
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -1,18 +1,16 @@
Track.name type:FT_POINTER Track.name max_size: 512
Track.gid type:FT_POINTER Track.gid max_size: 64
Track.restriction type:FT_POINTER Track.file max_count: 16
Track.alternative type:FT_POINTER Track.artist max_count: 8
Track.file type:FT_POINTER AudioFile.file_id max_size: 128
Track.artist type:FT_POINTER Image.file_id max_size: 128
AudioFile.file_id type:FT_POINTER Artist.gid max_size: 128
Image.file_id type:FT_POINTER Artist.name max_size: 512
Artist.gid type:FT_POINTER Album.name max_size: 512
Artist.name type:FT_POINTER Episode.gid max_size: 64
Album.name type:FT_POINTER Episode.name max_size: 512
Episode.gid type:FT_POINTER ImageGroup.image max_count: 10
Episode.name type:FT_POINTER Episode.audio max_count: 10
ImageGroup.image type:FT_POINTER Episode.covers max_count: 10
Episode.audio type:FT_POINTER Restriction.countries_allowed max_size: 32
Episode.covers type:FT_POINTER Restriction.countries_forbidden max_size: 32
Restriction.countries_allowed type:FT_POINTER
Restriction.countries_forbidden type:FT_POINTER

View File

@@ -15,16 +15,16 @@ PB_BIND(Restriction, Restriction, AUTO)
PB_BIND(Image, Image, 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) PB_BIND(Episode, Episode, 2)

View File

@@ -24,63 +24,78 @@ typedef enum _AudioFormat {
} AudioFormat; } AudioFormat;
/* Struct definitions */ /* Struct definitions */
typedef PB_BYTES_ARRAY_T(128) Artist_gid_t;
typedef struct _Artist { typedef struct _Artist {
pb_bytes_array_t *gid; bool has_gid;
char *name; Artist_gid_t gid;
bool has_name;
char name[512];
} Artist; } Artist;
typedef struct _Image { typedef PB_BYTES_ARRAY_T(128) AudioFile_file_id_t;
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 struct _AudioFile { typedef struct _AudioFile {
pb_bytes_array_t *file_id; bool has_file_id;
AudioFile_file_id_t file_id;
bool has_format; bool has_format;
AudioFormat format; AudioFormat format;
} AudioFile; } 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 { typedef struct _Episode {
pb_bytes_array_t *gid; bool has_gid;
char *name; Episode_gid_t gid;
bool has_name;
char name[512];
bool has_duration; bool has_duration;
int32_t duration; int32_t duration;
pb_size_t audio_count; pb_size_t audio_count;
struct _AudioFile *audio; AudioFile audio[10];
struct _ImageGroup *covers; bool has_covers;
ImageGroup covers;
} Episode; } Episode;
typedef PB_BYTES_ARRAY_T(64) Track_gid_t;
typedef struct _Track { typedef struct _Track {
pb_bytes_array_t *gid; bool has_gid;
char *name; Track_gid_t gid;
bool has_name;
char name[512];
bool has_album; bool has_album;
Album album; Album album;
pb_size_t artist_count; pb_size_t artist_count;
struct _Artist *artist; Artist artist[8];
bool has_duration; bool has_duration;
int32_t duration; int32_t duration;
pb_size_t restriction_count; pb_callback_t restriction;
struct _Restriction *restriction;
pb_size_t file_count; pb_size_t file_count;
struct _AudioFile *file; AudioFile file[16];
pb_size_t alternative_count; pb_callback_t alternative;
struct _Track *alternative;
} Track; } Track;
@@ -95,35 +110,35 @@ extern "C" {
#endif #endif
/* Initializer values for message structs */ /* Initializer values for message structs */
#define AudioFile_init_default {NULL, false, _AudioFormat_MIN} #define AudioFile_init_default {false, {0, {0}}, false, _AudioFormat_MIN}
#define Restriction_init_default {NULL, NULL} #define Restriction_init_default {false, "", false, ""}
#define Image_init_default {NULL} #define Image_init_default {false, {0, {0}}}
#define ImageGroup_init_default {0, NULL} #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}, NULL, false, ImageGroup_init_default} #define Album_init_default {{{NULL}, NULL}, false, "", false, ImageGroup_init_default}
#define Artist_init_default {NULL, NULL} #define Artist_init_default {false, {0, {0}}, false, ""}
#define Track_init_default {NULL, NULL, false, Album_init_default, 0, NULL, false, 0, 0, NULL, 0, NULL, 0, NULL} #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 {NULL, NULL, false, 0, 0, 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 {NULL, false, _AudioFormat_MIN} #define AudioFile_init_zero {false, {0, {0}}, false, _AudioFormat_MIN}
#define Restriction_init_zero {NULL, NULL} #define Restriction_init_zero {false, "", false, ""}
#define Image_init_zero {NULL} #define Image_init_zero {false, {0, {0}}}
#define ImageGroup_init_zero {0, NULL} #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}, NULL, false, ImageGroup_init_zero} #define Album_init_zero {{{NULL}, NULL}, false, "", false, ImageGroup_init_zero}
#define Artist_init_zero {NULL, NULL} #define Artist_init_zero {false, {0, {0}}, false, ""}
#define Track_init_zero {NULL, NULL, false, Album_init_zero, 0, NULL, false, 0, 0, NULL, 0, NULL, 0, NULL} #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 {NULL, NULL, false, 0, 0, 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) */ /* Field tags (for use in manual encoding/decoding) */
#define Artist_gid_tag 1 #define Artist_gid_tag 1
#define Artist_name_tag 2 #define Artist_name_tag 2
#define AudioFile_file_id_tag 1
#define AudioFile_format_tag 2
#define Image_file_id_tag 1 #define Image_file_id_tag 1
#define ImageGroup_image_tag 1
#define Restriction_countries_allowed_tag 2 #define Restriction_countries_allowed_tag 2
#define Restriction_countries_forbidden_tag 3 #define Restriction_countries_forbidden_tag 3
#define ImageGroup_image_tag 1
#define Album_gid_tag 1 #define Album_gid_tag 1
#define Album_name_tag 2 #define Album_name_tag 2
#define Album_cover_group_tag 17 #define Album_cover_group_tag 17
#define AudioFile_file_id_tag 1
#define AudioFile_format_tag 2
#define Episode_gid_tag 1 #define Episode_gid_tag 1
#define Episode_name_tag 2 #define Episode_name_tag 2
#define Episode_duration_tag 7 #define Episode_duration_tag 7
@@ -140,52 +155,52 @@ extern "C" {
/* Struct field encoding specification for nanopb */ /* Struct field encoding specification for nanopb */
#define AudioFile_FIELDLIST(X, a) \ #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) X(a, STATIC, OPTIONAL, UENUM, format, 2)
#define AudioFile_CALLBACK NULL #define AudioFile_CALLBACK NULL
#define AudioFile_DEFAULT NULL #define AudioFile_DEFAULT NULL
#define Restriction_FIELDLIST(X, a) \ #define Restriction_FIELDLIST(X, a) \
X(a, POINTER, OPTIONAL, STRING, countries_allowed, 2) \ X(a, STATIC, OPTIONAL, STRING, countries_allowed, 2) \
X(a, POINTER, OPTIONAL, STRING, countries_forbidden, 3) X(a, STATIC, OPTIONAL, STRING, countries_forbidden, 3)
#define Restriction_CALLBACK NULL #define Restriction_CALLBACK NULL
#define Restriction_DEFAULT NULL #define Restriction_DEFAULT NULL
#define Image_FIELDLIST(X, a) \ #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_CALLBACK NULL
#define Image_DEFAULT NULL #define Image_DEFAULT NULL
#define ImageGroup_FIELDLIST(X, a) \ #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_CALLBACK NULL
#define ImageGroup_DEFAULT NULL #define ImageGroup_DEFAULT NULL
#define ImageGroup_image_MSGTYPE Image #define ImageGroup_image_MSGTYPE Image
#define Album_FIELDLIST(X, a) \ #define Album_FIELDLIST(X, a) \
X(a, CALLBACK, OPTIONAL, BYTES, gid, 1) \ 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) X(a, STATIC, OPTIONAL, MESSAGE, cover_group, 17)
#define Album_CALLBACK pb_default_field_callback #define Album_CALLBACK pb_default_field_callback
#define Album_DEFAULT NULL #define Album_DEFAULT NULL
#define Album_cover_group_MSGTYPE ImageGroup #define Album_cover_group_MSGTYPE ImageGroup
#define Artist_FIELDLIST(X, a) \ #define Artist_FIELDLIST(X, a) \
X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ X(a, STATIC, OPTIONAL, BYTES, gid, 1) \
X(a, POINTER, OPTIONAL, STRING, name, 2) X(a, STATIC, OPTIONAL, STRING, name, 2)
#define Artist_CALLBACK NULL #define Artist_CALLBACK NULL
#define Artist_DEFAULT NULL #define Artist_DEFAULT NULL
#define Track_FIELDLIST(X, a) \ #define Track_FIELDLIST(X, a) \
X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ X(a, STATIC, OPTIONAL, BYTES, gid, 1) \
X(a, POINTER, OPTIONAL, STRING, name, 2) \ X(a, STATIC, OPTIONAL, STRING, name, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, album, 3) \ 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, STATIC, OPTIONAL, SINT32, duration, 7) \
X(a, POINTER, REPEATED, MESSAGE, restriction, 11) \ X(a, CALLBACK, REPEATED, MESSAGE, restriction, 11) \
X(a, POINTER, REPEATED, MESSAGE, file, 12) \ X(a, STATIC, REPEATED, MESSAGE, file, 12) \
X(a, POINTER, REPEATED, MESSAGE, alternative, 13) X(a, CALLBACK, REPEATED, MESSAGE, alternative, 13)
#define Track_CALLBACK NULL #define Track_CALLBACK pb_default_field_callback
#define Track_DEFAULT NULL #define Track_DEFAULT NULL
#define Track_album_MSGTYPE Album #define Track_album_MSGTYPE Album
#define Track_artist_MSGTYPE Artist #define Track_artist_MSGTYPE Artist
@@ -194,11 +209,11 @@ X(a, POINTER, REPEATED, MESSAGE, alternative, 13)
#define Track_alternative_MSGTYPE Track #define Track_alternative_MSGTYPE Track
#define Episode_FIELDLIST(X, a) \ #define Episode_FIELDLIST(X, a) \
X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ X(a, STATIC, OPTIONAL, BYTES, gid, 1) \
X(a, POINTER, OPTIONAL, STRING, name, 2) \ X(a, STATIC, OPTIONAL, STRING, name, 2) \
X(a, STATIC, OPTIONAL, SINT32, duration, 7) \ X(a, STATIC, OPTIONAL, SINT32, duration, 7) \
X(a, POINTER, REPEATED, MESSAGE, audio, 12) \ X(a, STATIC, REPEATED, MESSAGE, audio, 12) \
X(a, POINTER, OPTIONAL, MESSAGE, covers, 68) X(a, STATIC, OPTIONAL, MESSAGE, covers, 68)
#define Episode_CALLBACK NULL #define Episode_CALLBACK NULL
#define Episode_DEFAULT NULL #define Episode_DEFAULT NULL
#define Episode_audio_MSGTYPE AudioFile #define Episode_audio_MSGTYPE AudioFile
@@ -224,14 +239,14 @@ extern const pb_msgdesc_t Episode_msg;
#define Episode_fields &Episode_msg #define Episode_fields &Episode_msg
/* Maximum encoded size of messages (where known) */ /* 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 */ /* Album_size depends on runtime parameters */
/* Artist_size depends on runtime parameters */
/* Track_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 #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -1,13 +1,12 @@
Frame.ident type:FT_POINTER Frame.ident max_size: 64, fixed_length:false
Frame.protocol_version type:FT_POINTER Frame.protocol_version max_size: 64, fixed_length:false
Frame.recipient type:FT_POINTER Frame.recipient max_count: 64, max_size: 64
Capability.stringValue max_count:50, max_size: 50 Capability.stringValue max_count:50, max_size: 50
Capability.intValue max_count:50 Capability.intValue max_count:50
DeviceState.sw_version type:FT_POINTER DeviceState.sw_version max_size: 64, fixed_length:false
DeviceState.name type:FT_POINTER DeviceState.name max_size: 64, fixed_length:false
DeviceState.capabilities max_count:17, fixed_count: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 State.track max_count:100, fixed_count:false
TrackRef.gid type:FT_POINTER TrackRef.gid max_size: 128, fixed_length:false
TrackRef.uri type:FT_POINTER TrackRef.uri max_size: 256 fixed_length:false
TrackRef.context type:FT_POINTER

View File

@@ -6,7 +6,7 @@
#error Regenerate this file with the current version of nanopb generator. #error Regenerate this file with the current version of nanopb generator.
#endif #endif
PB_BIND(TrackRef, TrackRef, AUTO) PB_BIND(TrackRef, TrackRef, 2)
PB_BIND(State, State, 4) PB_BIND(State, State, 4)

View File

@@ -62,23 +62,28 @@ typedef struct _Capability {
char stringValue[50][50]; char stringValue[50][50];
} Capability; } Capability;
typedef PB_BYTES_ARRAY_T(128) TrackRef_gid_t;
typedef struct _TrackRef { typedef struct _TrackRef {
pb_bytes_array_t *gid; bool has_gid;
char *uri; TrackRef_gid_t gid;
bool has_uri;
char uri[256];
bool has_queued; bool has_queued;
bool queued; bool queued;
char *context; pb_callback_t context;
} TrackRef; } TrackRef;
typedef struct _DeviceState { typedef struct _DeviceState {
char *sw_version; bool has_sw_version;
char sw_version[64];
bool has_is_active; bool has_is_active;
bool is_active; bool is_active;
bool has_can_play; bool has_can_play;
bool can_play; bool can_play;
bool has_volume; bool has_volume;
uint32_t volume; uint32_t volume;
char *name; bool has_name;
char name[64];
bool has_error_code; bool has_error_code;
uint32_t error_code; uint32_t error_code;
bool has_became_active_at; bool has_became_active_at;
@@ -90,7 +95,8 @@ typedef struct _DeviceState {
} DeviceState; } DeviceState;
typedef struct _State { typedef struct _State {
char *context_uri; bool has_context_uri;
char context_uri[256];
bool has_index; bool has_index;
uint32_t index; uint32_t index;
bool has_position_ms; bool has_position_ms;
@@ -113,8 +119,10 @@ typedef struct _State {
typedef struct _Frame { typedef struct _Frame {
bool has_version; bool has_version;
uint32_t version; uint32_t version;
char *ident; bool has_ident;
char *protocol_version; char ident[64];
bool has_protocol_version;
char protocol_version[64];
bool has_seq_nr; bool has_seq_nr;
uint32_t seq_nr; uint32_t seq_nr;
bool has_typ; bool has_typ;
@@ -130,7 +138,7 @@ typedef struct _Frame {
bool has_state_update_id; bool has_state_update_id;
int64_t state_update_id; int64_t state_update_id;
pb_size_t recipient_count; pb_size_t recipient_count;
char **recipient; char recipient[64][64];
} Frame; } Frame;
@@ -153,16 +161,16 @@ extern "C" {
#endif #endif
/* Initializer values for message structs */ /* Initializer values for message structs */
#define TrackRef_init_default {NULL, NULL, false, 0, NULL} #define TrackRef_init_default {false, {0, {0}}, false, "", false, 0, {{NULL}, 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 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 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 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, NULL, NULL, false, 0, false, _MessageType_MIN, false, DeviceState_init_default, false, State_init_default, false, 0, false, 0, false, 0, 0, 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 {NULL, NULL, false, 0, NULL} #define TrackRef_init_zero {false, {0, {0}}, false, "", false, 0, {{NULL}, 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 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 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 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, NULL, NULL, false, 0, false, _MessageType_MIN, false, DeviceState_init_zero, false, State_init_zero, false, 0, false, 0, false, 0, 0, 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) */ /* Field tags (for use in manual encoding/decoding) */
#define Capability_typ_tag 1 #define Capability_typ_tag 1
@@ -206,15 +214,15 @@ extern "C" {
/* Struct field encoding specification for nanopb */ /* Struct field encoding specification for nanopb */
#define TrackRef_FIELDLIST(X, a) \ #define TrackRef_FIELDLIST(X, a) \
X(a, POINTER, OPTIONAL, BYTES, gid, 1) \ X(a, STATIC, OPTIONAL, BYTES, gid, 1) \
X(a, POINTER, OPTIONAL, STRING, uri, 2) \ X(a, STATIC, OPTIONAL, STRING, uri, 2) \
X(a, STATIC, OPTIONAL, BOOL, queued, 3) \ X(a, STATIC, OPTIONAL, BOOL, queued, 3) \
X(a, POINTER, OPTIONAL, STRING, context, 4) X(a, CALLBACK, OPTIONAL, STRING, context, 4)
#define TrackRef_CALLBACK NULL #define TrackRef_CALLBACK pb_default_field_callback
#define TrackRef_DEFAULT NULL #define TrackRef_DEFAULT NULL
#define State_FIELDLIST(X, a) \ #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, index, 3) \
X(a, STATIC, OPTIONAL, UINT32, position_ms, 4) \ X(a, STATIC, OPTIONAL, UINT32, position_ms, 4) \
X(a, STATIC, OPTIONAL, UENUM, status, 5) \ 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 Capability_DEFAULT (const pb_byte_t*)"\x08\x01\x00"
#define DeviceState_FIELDLIST(X, a) \ #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, is_active, 10) \
X(a, STATIC, OPTIONAL, BOOL, can_play, 11) \ X(a, STATIC, OPTIONAL, BOOL, can_play, 11) \
X(a, STATIC, OPTIONAL, UINT32, volume, 12) \ 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, UINT32, error_code, 14) \
X(a, STATIC, OPTIONAL, INT64, became_active_at, 15) \ X(a, STATIC, OPTIONAL, INT64, became_active_at, 15) \
X(a, CALLBACK, OPTIONAL, STRING, error_message, 16) \ 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) \ #define Frame_FIELDLIST(X, a) \
X(a, STATIC, OPTIONAL, UINT32, version, 1) \ X(a, STATIC, OPTIONAL, UINT32, version, 1) \
X(a, POINTER, OPTIONAL, STRING, ident, 2) \ X(a, STATIC, OPTIONAL, STRING, ident, 2) \
X(a, POINTER, OPTIONAL, STRING, protocol_version, 3) \ X(a, STATIC, OPTIONAL, STRING, protocol_version, 3) \
X(a, STATIC, OPTIONAL, UINT32, seq_nr, 4) \ X(a, STATIC, OPTIONAL, UINT32, seq_nr, 4) \
X(a, STATIC, OPTIONAL, UENUM, typ, 5) \ X(a, STATIC, OPTIONAL, UENUM, typ, 5) \
X(a, STATIC, OPTIONAL, MESSAGE, device_state, 7) \ 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, position, 13) \
X(a, STATIC, OPTIONAL, UINT32, volume, 14) \ X(a, STATIC, OPTIONAL, UINT32, volume, 14) \
X(a, STATIC, OPTIONAL, INT64, state_update_id, 17) \ 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_CALLBACK NULL
#define Frame_DEFAULT (const pb_byte_t*)"\x28\x01\x00" #define Frame_DEFAULT (const pb_byte_t*)"\x28\x01\x00"
#define Frame_device_state_MSGTYPE DeviceState #define Frame_device_state_MSGTYPE DeviceState

View File

@@ -11,7 +11,7 @@ std::map<MercuryType, std::string> MercuryTypeMap({
MercuryManager::MercuryManager(std::unique_ptr<Session> session): bell::Task("mercuryManager", 6 * 1024, 2, 1) MercuryManager::MercuryManager(std::unique_ptr<Session> session): bell::Task("mercuryManager", 6 * 1024, 2, 1)
{ {
tempMercuryHeader = Header_init_default; tempMercuryHeader = {};
this->timeProvider = std::make_shared<TimeProvider>(); this->timeProvider = std::make_shared<TimeProvider>();
this->callbacks = std::map<uint64_t, mercuryCallback>(); this->callbacks = std::map<uint64_t, mercuryCallback>();
this->subscriptions = std::map<std::string, mercuryCallback>(); this->subscriptions = std::map<std::string, mercuryCallback>();
@@ -294,8 +294,11 @@ uint64_t MercuryManager::execute(MercuryType method, std::string uri, mercuryCal
// Construct mercury header // Construct mercury header
CSPOT_LOG(debug, "executing MercuryType %s", MercuryTypeMap[method].c_str()); CSPOT_LOG(debug, "executing MercuryType %s", MercuryTypeMap[method].c_str());
tempMercuryHeader.uri = (char *)(uri.c_str()); pbPutString(uri, tempMercuryHeader.uri);
tempMercuryHeader.method = (char *)(MercuryTypeMap[method].c_str()); pbPutString(MercuryTypeMap[method], tempMercuryHeader.method);
tempMercuryHeader.has_method = true;
tempMercuryHeader.has_uri = true;
// GET and SEND are actually the same. Therefore the override // GET and SEND are actually the same. Therefore the override
// The difference between them is only in header's method // The difference between them is only in header's method

View File

@@ -3,13 +3,12 @@
MercuryResponse::MercuryResponse(std::vector<uint8_t> &data) MercuryResponse::MercuryResponse(std::vector<uint8_t> &data)
{ {
// this->mercuryHeader = std::make_unique<Header>(); // this->mercuryHeader = std::make_unique<Header>();
this->mercuryHeader = Header_init_default; this->mercuryHeader = {};
this->parts = mercuryParts(0); this->parts = mercuryParts(0);
this->parseResponse(data); this->parseResponse(data);
} }
MercuryResponse::~MercuryResponse() { MercuryResponse::~MercuryResponse() {
pb_release(Header_fields, &mercuryHeader);
} }
void MercuryResponse::parseResponse(std::vector<uint8_t> &data) void MercuryResponse::parseResponse(std::vector<uint8_t> &data)

View File

@@ -1,6 +1,6 @@
#include "Packet.h" #include "Packet.h"
Packet::Packet(uint8_t command, std::vector<uint8_t> &data) { Packet::Packet(uint8_t command, const std::vector<uint8_t> &data) {
this->command = command; this->command = command;
this->data = data; this->data = data;
}; };

View File

@@ -24,7 +24,8 @@ PlayerState::PlayerState(std::shared_ptr<TimeProvider> timeProvider)
innerFrame.state.repeat = false; innerFrame.state.repeat = false;
innerFrame.state.has_repeat = true; 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.is_active = false;
innerFrame.device_state.has_is_active = true; innerFrame.device_state.has_is_active = true;
@@ -35,7 +36,8 @@ PlayerState::PlayerState(std::shared_ptr<TimeProvider> timeProvider)
innerFrame.device_state.volume = configMan->volume; innerFrame.device_state.volume = configMan->volume;
innerFrame.device_state.has_volume = true; 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 // Prepare player's capabilities
addCapability(CapabilityType_kCanBePlayer, 1); addCapability(CapabilityType_kCanBePlayer, 1);
@@ -137,7 +139,8 @@ void PlayerState::updatePositionMs(uint32_t position)
void PlayerState::updateTracks() void PlayerState::updateTracks()
{ {
CSPOT_LOG(info, "---- Track count %d", remoteFrame.state.track_count); 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)); 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.track_count = remoteFrame.state.track_count;
innerFrame.state.has_playing_track_index = true; innerFrame.state.has_playing_track_index = true;
@@ -198,9 +201,14 @@ std::vector<uint8_t> PlayerState::encodeCurrentFrame(MessageType typ)
{ {
// Prepare current frame info // Prepare current frame info
innerFrame.version = 1; innerFrame.version = 1;
innerFrame.ident = (char *) deviceId;
pbPutCharArray(deviceId, innerFrame.ident);
innerFrame.has_ident = true;
innerFrame.seq_nr = this->seqNum; innerFrame.seq_nr = this->seqNum;
innerFrame.protocol_version = (char*) protocolVersion; pbPutCharArray(protocolVersion, innerFrame.protocol_version);
innerFrame.has_protocol_version = true;
innerFrame.typ = typ; innerFrame.typ = typ;
innerFrame.state_update_id = timeProvider->getSyncedTimestamp(); innerFrame.state_update_id = timeProvider->getSyncedTimestamp();
innerFrame.has_version = true; innerFrame.has_version = true;

View File

@@ -49,17 +49,26 @@ std::vector<uint8_t> Session::authenticate(std::shared_ptr<LoginBlob> blob)
authBlob = blob; authBlob = blob;
// prepare authentication request proto // prepare authentication request proto
authRequest.login_credentials.username = (char *)(blob->username.c_str()); pbPutString(blob->username, authRequest.login_credentials.username);
authRequest.login_credentials.auth_data = vectorToPbArray(blob->authData);
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.login_credentials.typ = (AuthenticationType) blob->authType;
authRequest.system_info.cpu_family = CpuFamily_CPU_UNKNOWN; authRequest.system_info.cpu_family = CpuFamily_CPU_UNKNOWN;
authRequest.system_info.os = Os_OS_UNKNOWN; authRequest.system_info.os = Os_OS_UNKNOWN;
authRequest.system_info.system_information_string = (char *)informationString;
authRequest.system_info.device_id = (char *)deviceId; auto infoStr = std::string(informationString);
authRequest.version_string = (char *)versionString; 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); auto data = pbEncode(ClientResponseEncrypted_fields, &authRequest);
free(authRequest.login_credentials.auth_data);
// Send login request // Send login request
this->shanConn->sendPacket(LOGIN_REQUEST_COMMAND, data); this->shanConn->sendPacket(LOGIN_REQUEST_COMMAND, data);

View File

@@ -10,8 +10,8 @@ SpotifyTrack::SpotifyTrack(std::shared_ptr<MercuryManager> manager, std::shared_
{ {
this->manager = manager; this->manager = manager;
this->fileId = std::vector<uint8_t>(); this->fileId = std::vector<uint8_t>();
episodeInfo = Episode_init_default; episodeInfo = {};
trackInfo = Track_init_default; trackInfo = {};
mercuryCallback trackResponseLambda = [=](std::unique_ptr<MercuryResponse> res) { mercuryCallback trackResponseLambda = [=](std::unique_ptr<MercuryResponse> res) {
this->trackInformationCallback(std::move(res), position_ms, isPaused); this->trackInformationCallback(std::move(res), position_ms, isPaused);
@@ -53,18 +53,18 @@ bool SpotifyTrack::countryListContains(std::string countryList, std::string coun
bool SpotifyTrack::canPlayTrack() bool SpotifyTrack::canPlayTrack()
{ {
for (int x = 0; x < trackInfo.restriction_count; x++) // for (int x = 0; x < trackInfo.restriction_count; x++)
{ // {
if (trackInfo.restriction[x].countries_allowed != nullptr) // if (strlen(trackInfo.restriction[x].countries_allowed) > 0)
{ // {
return countryListContains(std::string(trackInfo.restriction[x].countries_allowed), manager->countryCode); // return countryListContains(std::string(trackInfo.restriction[x].countries_allowed), manager->countryCode);
} // }
//
if (trackInfo.restriction[x].countries_forbidden != nullptr) // if (strlen(trackInfo.restriction[x].countries_forbidden) > 0)
{ // {
return !countryListContains(std::string(trackInfo.restriction[x].countries_forbidden), manager->countryCode); // return !countryListContains(std::string(trackInfo.restriction[x].countries_forbidden), manager->countryCode);
} // }
} // }
return true; return true;
} }
@@ -77,35 +77,39 @@ void SpotifyTrack::trackInformationCallback(std::unique_ptr<MercuryResponse> res
pb_release(Track_fields, &trackInfo); pb_release(Track_fields, &trackInfo);
pbDecode(trackInfo, Track_fields, response->parts[0]); 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); auto trackId = std::vector(trackInfo.gid.bytes, trackInfo.gid.bytes + trackInfo.gid.size);
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);
this->fileId = std::vector<uint8_t>(); this->fileId = std::vector<uint8_t>();
for (int x = 0; x < trackInfo.file_count; x++) for (int x = 0; x < trackInfo.file_count; x++)
{ {
if (trackInfo.file[x].format == configMan->format) 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 break; // If file found stop searching
} }
} }
if (trackInfoReceived != nullptr) 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 = { TrackInfo simpleTrackInfo = {
.name = std::string(trackInfo.name), .name = std::string(trackInfo.name),
.album = std::string(trackInfo.album.name), .album = std::string(trackInfo.album.name),
@@ -139,14 +143,15 @@ void SpotifyTrack::episodeInformationCallback(std::unique_ptr<MercuryResponse> r
{ {
if (episodeInfo.audio[x].format == AudioFormat_OGG_VORBIS_96) 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 break; // If file found stop searching
} }
} }
if (trackInfoReceived != nullptr) 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 = { TrackInfo simpleTrackInfo = {
.name = std::string(episodeInfo.name), .name = std::string(episodeInfo.name),
.album = "", .album = "",
@@ -159,7 +164,7 @@ void SpotifyTrack::episodeInformationCallback(std::unique_ptr<MercuryResponse> r
trackInfoReceived(simpleTrackInfo); 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<uint8_t> fileId, std::vector<uint8_t> trackId, int32_t trackDuration, uint32_t position_ms, bool isPaused) void SpotifyTrack::requestAudioKey(std::vector<uint8_t> fileId, std::vector<uint8_t> trackId, int32_t trackDuration, uint32_t position_ms, bool isPaused)

View File

@@ -3,11 +3,11 @@
TrackReference::TrackReference(TrackRef *ref) 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 uri = std::string(ref->uri);
auto idString = uri.substr(uri.find_last_of(":") + 1, uri.size()); auto idString = uri.substr(uri.find_last_of(":") + 1, uri.size());

View File

@@ -106,7 +106,7 @@ static bool cmd_handler(cspot_event_t event, ...) {
switch(event) { switch(event) {
case CSPOT_SETUP: case CSPOT_SETUP:
actrls_set(controls, false, NULL, actrls_ir_action); actrls_set(controls, false, NULL, actrls_ir_action);
displayer_control(DISPLAYER_ACTIVATE, "SPOTIFY"); displayer_control(DISPLAYER_ACTIVATE, "SPOTIFY", false);
break; break;
case CSPOT_PLAY: case CSPOT_PLAY:
displayer_control(DISPLAYER_TIMER_RUN); displayer_control(DISPLAYER_TIMER_RUN);