mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-06 19:47:02 +03:00
airplay artwork and CSpot leak fix (temporary)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ); }
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
BIN
components/display/note.jpg
Normal file
BIN
components/display/note.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -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);
|
||||
|
||||
@@ -628,6 +628,9 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
LOG_INFO("[%p]: received metadata", ctx);
|
||||
settings.ctx = &metadata;
|
||||
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);
|
||||
free_metadata(&metadata);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
|
||||
@@ -120,7 +120,8 @@ static void cspotTask(void *pvParameters) {
|
||||
case CSpotEventType::TRACK_INFO: {
|
||||
TrackInfo track = std::get<TrackInfo>(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: {
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
pb_istream_t pb_istream_from_http(bell::HTTPClient::HTTPResponse *response, size_t length = 0);
|
||||
|
||||
|
||||
@@ -47,6 +47,22 @@ pb_bytes_array_t* vectorToPbArray(const std::vector<uint8_t>& 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<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) {
|
||||
return std::vector<uint8_t>(pbArray->bytes, pbArray->bytes + pbArray->size);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ class Packet
|
||||
private:
|
||||
|
||||
public:
|
||||
Packet(uint8_t command, std::vector<uint8_t> &data);
|
||||
Packet(uint8_t command, const std::vector<uint8_t> &data);
|
||||
uint8_t command;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
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
|
||||
@@ -9,7 +9,7 @@
|
||||
PB_BIND(SystemInfo, SystemInfo, 2)
|
||||
|
||||
|
||||
PB_BIND(LoginCredentials, LoginCredentials, AUTO)
|
||||
PB_BIND(LoginCredentials, LoginCredentials, 2)
|
||||
|
||||
|
||||
PB_BIND(ClientResponseEncrypted, ClientResponseEncrypted, 2)
|
||||
|
||||
@@ -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" */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" */
|
||||
|
||||
@@ -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
|
||||
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
|
||||
@@ -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)
|
||||
|
||||
@@ -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" */
|
||||
|
||||
@@ -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
|
||||
TrackRef.gid max_size: 128, fixed_length:false
|
||||
TrackRef.uri max_size: 256 fixed_length:false
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -11,7 +11,7 @@ std::map<MercuryType, std::string> MercuryTypeMap({
|
||||
|
||||
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->callbacks = std::map<uint64_t, 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
|
||||
|
||||
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
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
MercuryResponse::MercuryResponse(std::vector<uint8_t> &data)
|
||||
{
|
||||
// this->mercuryHeader = std::make_unique<Header>();
|
||||
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<uint8_t> &data)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#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->data = data;
|
||||
};
|
||||
@@ -24,7 +24,8 @@ PlayerState::PlayerState(std::shared_ptr<TimeProvider> 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> 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<uint8_t> 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;
|
||||
|
||||
@@ -49,17 +49,26 @@ std::vector<uint8_t> Session::authenticate(std::shared_ptr<LoginBlob> 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);
|
||||
|
||||
@@ -10,8 +10,8 @@ SpotifyTrack::SpotifyTrack(std::shared_ptr<MercuryManager> manager, std::shared_
|
||||
{
|
||||
this->manager = manager;
|
||||
this->fileId = std::vector<uint8_t>();
|
||||
episodeInfo = Episode_init_default;
|
||||
trackInfo = Track_init_default;
|
||||
episodeInfo = {};
|
||||
trackInfo = {};
|
||||
|
||||
mercuryCallback trackResponseLambda = [=](std::unique_ptr<MercuryResponse> 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<MercuryResponse> 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<uint8_t>();
|
||||
|
||||
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<MercuryResponse> 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<MercuryResponse> 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<uint8_t> fileId, std::vector<uint8_t> trackId, int32_t trackDuration, uint32_t position_ms, bool isPaused)
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user