fix a big time bug in metadataChunk (off by one in an array assignment)
also, now we have metadata in our streams git-svn-id: https://svn.musicpd.org/mpd/trunk@2337 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
b6bcc65a45
commit
ce10ba4b11
@ -34,7 +34,7 @@ static AudioFormat * audio_configFormat = NULL;
|
||||
static AudioOutput * aoOutput = NULL;
|
||||
static AudioOutput * shoutOutput = NULL;
|
||||
|
||||
static void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
|
||||
void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
|
||||
if(!src) return;
|
||||
|
||||
dest->sampleRate = src->sampleRate;
|
||||
@ -182,3 +182,7 @@ void closeAudioDevice() {
|
||||
if(shoutOutput) closeAudioOutput(shoutOutput);
|
||||
closeAudioOutput(aoOutput);
|
||||
}
|
||||
|
||||
void sendMetdataToAudioDevice(MpdTag * tag) {
|
||||
if(shoutOutput) sendMetadataToAudioOutput(shoutOutput, tag);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../config.h"
|
||||
|
||||
#include "mpd_types.h"
|
||||
#include "tag.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -33,6 +34,8 @@ typedef struct _AudioFormat {
|
||||
volatile mpd_sint8 bits;
|
||||
} AudioFormat;
|
||||
|
||||
void copyAudioFormat(AudioFormat * dest, AudioFormat * src);
|
||||
|
||||
void getOutputAudioFormat(AudioFormat * inFormat, AudioFormat * outFormat);
|
||||
|
||||
int parseAudioConfig(AudioFormat * audioFormat, char * conf);
|
||||
@ -55,4 +58,6 @@ int isAudioDeviceOpen();
|
||||
|
||||
int isCurrentAudioFormat(AudioFormat * audioFormat);
|
||||
|
||||
void sendMetdataToAudioDevice(MpdTag * tag);
|
||||
|
||||
#endif
|
||||
|
@ -32,6 +32,7 @@ AudioOutput * newAudioOutput(char * name) {
|
||||
ret->openDeviceFunc = plugin->openDeviceFunc;
|
||||
ret->playFunc = plugin->playFunc;
|
||||
ret->closeDeviceFunc = plugin->closeDeviceFunc;
|
||||
ret->sendMetdataFunc = plugin->sendMetdataFunc;
|
||||
ret->open = 0;
|
||||
|
||||
if(plugin->initDriverFunc(ret) != 0) {
|
||||
@ -62,3 +63,8 @@ void finishAudioOutput(AudioOutput * audioOutput) {
|
||||
audioOutput->finishDriverFunc(audioOutput);
|
||||
free(audioOutput);
|
||||
}
|
||||
|
||||
void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag) {
|
||||
if(!audioOutput->open || !audioOutput->sendMetdataFunc) return;
|
||||
audioOutput->sendMetdataFunc(audioOutput, tag);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "mpd_types.h"
|
||||
#include "audio.h"
|
||||
#include "tag.h"
|
||||
|
||||
#define AUDIO_AO_DRIVER_DEFAULT "default"
|
||||
|
||||
@ -40,7 +41,8 @@ typedef int (* AudioOutputPlayFunc) (AudioOutput * audioOutput,
|
||||
|
||||
typedef void (* AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput);
|
||||
|
||||
typedef int (* AudioOutputKeepAliveFunc) (AudioOutput * audioOutput, int ms);
|
||||
typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput,
|
||||
MpdTag * tag);
|
||||
|
||||
struct _AudioOutput {
|
||||
int open;
|
||||
@ -49,7 +51,7 @@ struct _AudioOutput {
|
||||
AudioOutputOpenDeviceFunc openDeviceFunc;
|
||||
AudioOutputPlayFunc playFunc;
|
||||
AudioOutputCloseDeviceFunc closeDeviceFunc;
|
||||
AudioOutputKeepAliveFunc keepAliveFunc;
|
||||
AudioOutputSendMetadataFunc sendMetdataFunc;
|
||||
|
||||
void * data;
|
||||
};
|
||||
@ -62,7 +64,7 @@ typedef struct _AudioOutputPlugin {
|
||||
AudioOutputOpenDeviceFunc openDeviceFunc;
|
||||
AudioOutputPlayFunc playFunc;
|
||||
AudioOutputCloseDeviceFunc closeDeviceFunc;
|
||||
AudioOutputKeepAliveFunc keepAliveFunc;
|
||||
AudioOutputSendMetadataFunc sendMetdataFunc;
|
||||
} AudioOutputPlugin;
|
||||
|
||||
void initAudioOutputPlugins();
|
||||
@ -77,5 +79,6 @@ int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size);
|
||||
void closeAudioOutput(AudioOutput * audioOutput);
|
||||
void finishAudioOutput(AudioOutput * audioOutput);
|
||||
int keepAudioOutputAlive(AudioOutput * audioOutput, int ms);
|
||||
void sendMetadataToAudioOutput(AudioOutput * audioOutput, MpdTag * tag);
|
||||
|
||||
#endif
|
||||
|
@ -225,5 +225,6 @@ AudioOutputPlugin aoPlugin =
|
||||
audioOutputAo_finishDriver,
|
||||
audioOutputAo_openDevice,
|
||||
audioOutputAo_play,
|
||||
audioOutputAo_closeDevice
|
||||
audioOutputAo_closeDevice,
|
||||
NULL /* sendMetadataFunc */
|
||||
};
|
||||
|
@ -54,8 +54,6 @@ typedef struct _ShoutData {
|
||||
vorbis_info vi;
|
||||
vorbis_comment vc;
|
||||
|
||||
int serialno;
|
||||
|
||||
float quality;
|
||||
AudioFormat outAudioFormat;
|
||||
AudioFormat inAudioFormat;
|
||||
@ -72,7 +70,6 @@ static ShoutData * newShoutData() {
|
||||
ShoutData * ret = malloc(sizeof(ShoutData));
|
||||
|
||||
ret->shoutConn = shout_new();
|
||||
ret->serialno = rand();
|
||||
ret->convBuffer = NULL;
|
||||
ret->convBufferLen = 0;
|
||||
ret->opened = 0;
|
||||
@ -190,6 +187,14 @@ static int shout_initDriver(AudioOutput * audioOutput) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clearEncoder(ShoutData * sd) {
|
||||
ogg_stream_clear(&(sd->os));
|
||||
vorbis_block_clear(&(sd->vb));
|
||||
vorbis_dsp_clear(&(sd->vd));
|
||||
vorbis_comment_clear(&(sd->vc));
|
||||
vorbis_info_clear(&(sd->vi));
|
||||
}
|
||||
|
||||
static void shout_closeShoutConn(ShoutData * sd) {
|
||||
if(sd->opened) {
|
||||
if(shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) {
|
||||
@ -197,11 +202,7 @@ static void shout_closeShoutConn(ShoutData * sd) {
|
||||
"%s\n", shout_get_error(sd->shoutConn));
|
||||
}
|
||||
|
||||
ogg_stream_clear(&(sd->os));
|
||||
vorbis_block_clear(&(sd->vb));
|
||||
vorbis_dsp_clear(&(sd->vd));
|
||||
vorbis_comment_clear(&(sd->vc));
|
||||
vorbis_info_clear(&(sd->vi));
|
||||
clearEncoder(sd);
|
||||
}
|
||||
|
||||
sd->opened = 0;
|
||||
@ -250,6 +251,27 @@ static void write_page(ShoutData * sd) {
|
||||
/*shout_sync(sd->shoutConn);*/
|
||||
}
|
||||
|
||||
static int initEncoder(ShoutData * sd) {
|
||||
vorbis_info_init(&(sd->vi));
|
||||
|
||||
if( 0 != vorbis_encode_init_vbr(&(sd->vi), sd->outAudioFormat.channels,
|
||||
sd->outAudioFormat.sampleRate, sd->quality) )
|
||||
{
|
||||
ERROR("problem seting up vorbis encoder for shout\n");
|
||||
vorbis_info_clear(&(sd->vi));
|
||||
return -1;
|
||||
}
|
||||
|
||||
vorbis_analysis_init(&(sd->vd), &(sd->vi));
|
||||
vorbis_block_init (&(sd->vd), &(sd->vb));
|
||||
|
||||
ogg_stream_init(&(sd->os), rand());
|
||||
|
||||
vorbis_comment_init(&(sd->vc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shout_openDevice(AudioOutput * audioOutput,
|
||||
AudioFormat * audioFormat)
|
||||
{
|
||||
@ -277,24 +299,12 @@ static int shout_openDevice(AudioOutput * audioOutput,
|
||||
return -1;
|
||||
}
|
||||
|
||||
vorbis_info_init(&(sd->vi));
|
||||
|
||||
if( 0 != vorbis_encode_init_vbr(&(sd->vi), sd->outAudioFormat.channels,
|
||||
sd->outAudioFormat.sampleRate, sd->quality) )
|
||||
{
|
||||
ERROR("problem seting up vorbis encoder for shout\n");
|
||||
vorbis_info_clear(&(sd->vi));
|
||||
if(initEncoder(sd) < 0) {
|
||||
shout_close(sd->shoutConn);
|
||||
audioOutput->open = 0;
|
||||
audioOutput->open = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
vorbis_analysis_init(&(sd->vd), &(sd->vi));
|
||||
vorbis_block_init (&(sd->vd), &(sd->vb));
|
||||
|
||||
ogg_stream_init(&(sd->os), sd->serialno);
|
||||
|
||||
vorbis_comment_init(&(sd->vc));
|
||||
vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main),
|
||||
&(sd->header_comments), &(sd->header_codebooks));
|
||||
|
||||
@ -375,6 +385,44 @@ static int shout_play(AudioOutput * audioOutput, char * playChunk, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define addTag(name, value) { \
|
||||
if(value) vorbis_comment_add_tag(&(sd->vc), name, value); \
|
||||
}
|
||||
|
||||
static void shout_sendMetadata(AudioOutput * audioOutput, MpdTag * tag) {
|
||||
ShoutData * sd = (ShoutData *)audioOutput->data;
|
||||
ogg_int64_t granulepos = sd->vd.granulepos;
|
||||
|
||||
clearEncoder(sd);
|
||||
if(initEncoder(sd) < 0) return;
|
||||
|
||||
sd->vd.granulepos = granulepos;
|
||||
|
||||
if(tag) {
|
||||
addTag("ARTIST", tag->artist);
|
||||
addTag("ALBUM", tag->album);
|
||||
addTag("TITLE", tag->title);
|
||||
|
||||
}
|
||||
|
||||
DEBUG("shout: got tag\n");
|
||||
|
||||
vorbis_analysis_headerout(&(sd->vd), &(sd->vc), &(sd->header_main),
|
||||
&(sd->header_comments), &(sd->header_codebooks));
|
||||
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_main));
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_comments));
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_codebooks));
|
||||
|
||||
/*vorbis_commentheader_out(&(sd->vc), &(sd->header_comments));
|
||||
ogg_stream_packetin(&(sd->os), &(sd->header_comments));*/
|
||||
|
||||
while(ogg_stream_flush(&(sd->os), &(sd->og)))
|
||||
{
|
||||
write_page(sd);
|
||||
}
|
||||
}
|
||||
|
||||
AudioOutputPlugin shoutPlugin =
|
||||
{
|
||||
"shout",
|
||||
@ -382,7 +430,8 @@ AudioOutputPlugin shoutPlugin =
|
||||
shout_finishDriver,
|
||||
shout_openDevice,
|
||||
shout_play,
|
||||
shout_closeDevice
|
||||
shout_closeDevice,
|
||||
shout_sendMetadata
|
||||
};
|
||||
|
||||
#else
|
||||
@ -396,6 +445,7 @@ AudioOutputPlugin shoutPlugin =
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
10
src/decode.c
10
src/decode.c
@ -145,6 +145,7 @@ int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
|
||||
{
|
||||
strncpy(pc->currentUrl, pc->utf8url, MAXPATHLEN);
|
||||
pc->currentUrl[MAXPATHLEN] = '\0';
|
||||
MpdTag * tag = NULL;
|
||||
|
||||
while(decode_pid && *decode_pid>0 && dc->start) my_usleep(10000);
|
||||
|
||||
@ -156,8 +157,14 @@ int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((tag = metadataChunkToMpdTagDup(&(pc->fileMetadataChunk)))) {
|
||||
sendMetdataToAudioDevice(tag);
|
||||
printMpdTag(stdout, tag);
|
||||
freeMpdTag(tag);
|
||||
tag = NULL;
|
||||
}
|
||||
|
||||
pc->totalTime = pc->fileTime;
|
||||
pc->elapsedTime = 0;
|
||||
pc->bitRate = 0;
|
||||
pc->sampleRate = 0;
|
||||
pc->bits = 0;
|
||||
@ -465,6 +472,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
|
||||
|
||||
if(waitOnDecode(pc,dc,cb,&decodeWaitedOn)<0) return;
|
||||
|
||||
pc->elapsedTime = 0;
|
||||
pc->state = PLAYER_STATE_PLAY;
|
||||
pc->play = 0;
|
||||
kill(getppid(),SIGUSR1);
|
||||
|
@ -38,7 +38,7 @@ void initMetadataChunk(MetadataChunk * chunk) {
|
||||
MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk) {
|
||||
MpdTag * ret = newMpdTag();
|
||||
|
||||
chunk->buffer[METADATA_BUFFER_LENGTH] = '\0';
|
||||
chunk->buffer[METADATA_BUFFER_LENGTH-1] = '\0';
|
||||
|
||||
dupElementToTag(ret->name, chunk->name);
|
||||
dupElementToTag(ret->title, chunk->title);
|
||||
@ -65,6 +65,8 @@ void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk) {
|
||||
|
||||
initMetadataChunk(chunk);
|
||||
|
||||
if(!tag) return;
|
||||
|
||||
copyStringToChunk(tag->name, chunk->name);
|
||||
copyStringToChunk(tag->title, chunk->title);
|
||||
copyStringToChunk(tag->artist, chunk->artist);
|
||||
|
@ -187,6 +187,8 @@ int playerPlay(FILE * fp, Song * song) {
|
||||
if(song->tag) pc->fileTime = song->tag->time;
|
||||
else pc->fileTime = 0;
|
||||
|
||||
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
|
||||
|
||||
strncpy(pc->utf8url, song->utf8url, MAXPATHLEN);
|
||||
pc->utf8url[MAXPATHLEN] = '\0';
|
||||
|
||||
@ -338,6 +340,8 @@ int queueSong(Song * song) {
|
||||
if(song->tag) pc->fileTime = song->tag->time;
|
||||
else pc->fileTime = 0;
|
||||
|
||||
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
|
||||
|
||||
pc->queueState = PLAYER_QUEUE_FULL;
|
||||
return 0;
|
||||
}
|
||||
@ -390,6 +394,8 @@ int playerSeek(FILE * fp, Song * song, float time) {
|
||||
if(song->tag) pc->fileTime = song->tag->time;
|
||||
else pc->fileTime = 0;
|
||||
|
||||
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
|
||||
|
||||
strncpy(pc->utf8url, song->utf8url, MAXPATHLEN);
|
||||
pc->utf8url[MAXPATHLEN] = '\0';
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ typedef struct _PlayerControl {
|
||||
volatile mpd_sint8 cycleLogFiles;
|
||||
volatile mpd_sint8 metadataState;
|
||||
MetadataChunk metadataChunk;
|
||||
MetadataChunk fileMetadataChunk;
|
||||
} PlayerControl;
|
||||
|
||||
void clearPlayerPid();
|
||||
|
Loading…
Reference in New Issue
Block a user