Commit d7a18b97 authored by Led's avatar Led

0.11.0-pre2

parent 887593ce
1) put some sort of error reporting for streaming/inputStream! *) put some sort of error reporting for streaming/inputStream!
2) Fix charset errors so they don't goto stderr/out *) Fix charset errors so they don't goto stderr/out
*) compute time of vorbis from actual number of samples played
*) remove previous hack for streams
Post-1.0 Post-1.0
-------- --------
......
...@@ -110,6 +110,10 @@ playlistinfo <int song> ...@@ -110,6 +110,10 @@ playlistinfo <int song>
displays list of songs in the playlist displays list of songs in the playlist
_song_ is optional and species a single song to displa info for _song_ is optional and species a single song to displa info for
plchanges <playlist version>
displays changed songs currently in the playlist since
_playlist version_
previous previous
plays previous song in playlist plays previous song in playlist
...@@ -198,6 +202,10 @@ at once using a command list. The command list beings with: ...@@ -198,6 +202,10 @@ at once using a command list. The command list beings with:
command_list_begin command_list_begin
or:
command_list_ok_begin
And ends with: And ends with:
command_list_end command_list_end
...@@ -205,4 +213,5 @@ command_list_end ...@@ -205,4 +213,5 @@ command_list_end
It does not execute any commands until the list has ended. The return It does not execute any commands until the list has ended. The return
value is whatever the return for a list of commands is. On success value is whatever the return for a list of commands is. On success
for all commands, OK is returned. If a command fails, no more commands for all commands, OK is returned. If a command fails, no more commands
are executed and the appropriate ACK error is returned. are executed and the appropriate ACK error is returned. If "command_list_ok_begin is used", "list_OK\n" is returned for each successful command executed
in the command list.
...@@ -4,7 +4,7 @@ SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR) $(MP4FF_SUBDIR) ...@@ -4,7 +4,7 @@ SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR) $(MP4FF_SUBDIR)
mpd_inputPlugins = inputPlugins/mp3_plugin.c inputPlugins/ogg_plugin.c \ mpd_inputPlugins = inputPlugins/mp3_plugin.c inputPlugins/ogg_plugin.c \
inputPlugins/flac_plugin.c inputPlugins/audiofile_plugin.c \ inputPlugins/flac_plugin.c inputPlugins/audiofile_plugin.c \
inputPlugins/mp4_plugin.c inputPlugins/aac_plugin.c \ inputPlugins/mp4_plugin.c inputPlugins/aac_plugin.c \
inputPlugins/mod_plugin.c inputPlugins/mod_plugin.c
mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
song.h list.h directory.h tables.h utils.h path.h \ song.h list.h directory.h tables.h utils.h path.h \
...@@ -13,7 +13,7 @@ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \ ...@@ -13,7 +13,7 @@ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
charConv.h permission.h mpd_types.h pcm_utils.h \ charConv.h permission.h mpd_types.h pcm_utils.h \
signal_check.h utf8.h inputStream.h \ signal_check.h utf8.h inputStream.h \
outputBuffer.h replayGain.h inputStream_file.h inputStream_http.h \ outputBuffer.h replayGain.h inputStream_file.h inputStream_http.h \
inputPlugin.h inputPlugin.h metadataChunk.h ack.h
mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
song.c list.c directory.c tables.c utils.c path.c \ song.c list.c directory.c tables.c utils.c path.c \
tag.c player.c listen.c conf.c volume.c \ tag.c player.c listen.c conf.c volume.c \
...@@ -21,7 +21,7 @@ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ ...@@ -21,7 +21,7 @@ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
charConv.c permission.c pcm_utils.c \ charConv.c permission.c pcm_utils.c \
signal_check.c utf8.c inputStream.c outputBuffer.c \ signal_check.c utf8.c inputStream.c outputBuffer.c \
replayGain.c inputStream_file.c inputStream_http.c inputPlugin.c \ replayGain.c inputStream_file.c inputStream_http.c inputPlugin.c \
$(mpd_headers) $(mpd_inputPlugins) metadataChunk.c $(mpd_headers) $(mpd_inputPlugins)
mpd_CFLAGS = $(MPD_CFLAGS) mpd_CFLAGS = $(MPD_CFLAGS)
mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB) $(MP4FF_LIB) mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB) $(MP4FF_LIB)
......
...@@ -116,7 +116,7 @@ SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR) $(MP4FF_SUBDIR) ...@@ -116,7 +116,7 @@ SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR) $(MP4FF_SUBDIR)
mpd_inputPlugins = inputPlugins/mp3_plugin.c inputPlugins/ogg_plugin.c \ mpd_inputPlugins = inputPlugins/mp3_plugin.c inputPlugins/ogg_plugin.c \
inputPlugins/flac_plugin.c inputPlugins/audiofile_plugin.c \ inputPlugins/flac_plugin.c inputPlugins/audiofile_plugin.c \
inputPlugins/mp4_plugin.c inputPlugins/aac_plugin.c \ inputPlugins/mp4_plugin.c inputPlugins/aac_plugin.c \
inputPlugins/mod_plugin.c inputPlugins/mod_plugin.c
mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
...@@ -126,7 +126,7 @@ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \ ...@@ -126,7 +126,7 @@ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
charConv.h permission.h mpd_types.h pcm_utils.h \ charConv.h permission.h mpd_types.h pcm_utils.h \
signal_check.h utf8.h inputStream.h \ signal_check.h utf8.h inputStream.h \
outputBuffer.h replayGain.h inputStream_file.h inputStream_http.h \ outputBuffer.h replayGain.h inputStream_file.h inputStream_http.h \
inputPlugin.h inputPlugin.h metadataChunk.h ack.h
mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
song.c list.c directory.c tables.c utils.c path.c \ song.c list.c directory.c tables.c utils.c path.c \
...@@ -135,7 +135,7 @@ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ ...@@ -135,7 +135,7 @@ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
charConv.c permission.c pcm_utils.c \ charConv.c permission.c pcm_utils.c \
signal_check.c utf8.c inputStream.c outputBuffer.c \ signal_check.c utf8.c inputStream.c outputBuffer.c \
replayGain.c inputStream_file.c inputStream_http.c inputPlugin.c \ replayGain.c inputStream_file.c inputStream_http.c inputPlugin.c \
$(mpd_headers) $(mpd_inputPlugins) metadataChunk.c $(mpd_headers) $(mpd_inputPlugins)
mpd_CFLAGS = $(MPD_CFLAGS) mpd_CFLAGS = $(MPD_CFLAGS)
...@@ -169,7 +169,7 @@ am_mpd_OBJECTS = mpd-main.$(OBJEXT) mpd-buffer2array.$(OBJEXT) \ ...@@ -169,7 +169,7 @@ am_mpd_OBJECTS = mpd-main.$(OBJEXT) mpd-buffer2array.$(OBJEXT) \
mpd-inputStream.$(OBJEXT) mpd-outputBuffer.$(OBJEXT) \ mpd-inputStream.$(OBJEXT) mpd-outputBuffer.$(OBJEXT) \
mpd-replayGain.$(OBJEXT) mpd-inputStream_file.$(OBJEXT) \ mpd-replayGain.$(OBJEXT) mpd-inputStream_file.$(OBJEXT) \
mpd-inputStream_http.$(OBJEXT) mpd-inputPlugin.$(OBJEXT) \ mpd-inputStream_http.$(OBJEXT) mpd-inputPlugin.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) mpd-metadataChunk.$(OBJEXT) $(am__objects_1) $(am__objects_2)
mpd_OBJECTS = $(am_mpd_OBJECTS) mpd_OBJECTS = $(am_mpd_OBJECTS)
mpd_DEPENDENCIES = mpd_DEPENDENCIES =
mpd_LDFLAGS = mpd_LDFLAGS =
...@@ -198,6 +198,7 @@ am__depfiles_maybe = depfiles ...@@ -198,6 +198,7 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-list.Po ./$(DEPDIR)/mpd-listen.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-list.Po ./$(DEPDIR)/mpd-listen.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-log.Po ./$(DEPDIR)/mpd-ls.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-log.Po ./$(DEPDIR)/mpd-ls.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-main.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-main.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-metadataChunk.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-mod_plugin.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-mod_plugin.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-mp3_plugin.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-mp3_plugin.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-mp4_plugin.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpd-mp4_plugin.Po \
...@@ -307,6 +308,7 @@ mpd-replayGain.$(OBJEXT): replayGain.c ...@@ -307,6 +308,7 @@ mpd-replayGain.$(OBJEXT): replayGain.c
mpd-inputStream_file.$(OBJEXT): inputStream_file.c mpd-inputStream_file.$(OBJEXT): inputStream_file.c
mpd-inputStream_http.$(OBJEXT): inputStream_http.c mpd-inputStream_http.$(OBJEXT): inputStream_http.c
mpd-inputPlugin.$(OBJEXT): inputPlugin.c mpd-inputPlugin.$(OBJEXT): inputPlugin.c
mpd-metadataChunk.$(OBJEXT): metadataChunk.c
mpd-mp3_plugin.$(OBJEXT): inputPlugins/mp3_plugin.c mpd-mp3_plugin.$(OBJEXT): inputPlugins/mp3_plugin.c
mpd-ogg_plugin.$(OBJEXT): inputPlugins/ogg_plugin.c mpd-ogg_plugin.$(OBJEXT): inputPlugins/ogg_plugin.c
mpd-flac_plugin.$(OBJEXT): inputPlugins/flac_plugin.c mpd-flac_plugin.$(OBJEXT): inputPlugins/flac_plugin.c
...@@ -344,6 +346,7 @@ distclean-compile: ...@@ -344,6 +346,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-log.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-ls.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-ls.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-metadataChunk.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-mod_plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-mod_plugin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-mp3_plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-mp3_plugin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-mp4_plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-mp4_plugin.Po@am__quote@
...@@ -1018,6 +1021,24 @@ mpd-inputPlugin.lo: inputPlugin.c ...@@ -1018,6 +1021,24 @@ mpd-inputPlugin.lo: inputPlugin.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-inputPlugin.lo `test -f 'inputPlugin.c' || echo '$(srcdir)/'`inputPlugin.c $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-inputPlugin.lo `test -f 'inputPlugin.c' || echo '$(srcdir)/'`inputPlugin.c
mpd-metadataChunk.o: metadataChunk.c
@AMDEP_TRUE@ source='metadataChunk.c' object='mpd-metadataChunk.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-metadataChunk.Po' tmpdepfile='$(DEPDIR)/mpd-metadataChunk.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-metadataChunk.o `test -f 'metadataChunk.c' || echo '$(srcdir)/'`metadataChunk.c
mpd-metadataChunk.obj: metadataChunk.c
@AMDEP_TRUE@ source='metadataChunk.c' object='mpd-metadataChunk.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-metadataChunk.Po' tmpdepfile='$(DEPDIR)/mpd-metadataChunk.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-metadataChunk.obj `cygpath -w metadataChunk.c`
mpd-metadataChunk.lo: metadataChunk.c
@AMDEP_TRUE@ source='metadataChunk.c' object='mpd-metadataChunk.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-metadataChunk.Plo' tmpdepfile='$(DEPDIR)/mpd-metadataChunk.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-metadataChunk.lo `test -f 'metadataChunk.c' || echo '$(srcdir)/'`metadataChunk.c
mpd-mp3_plugin.o: inputPlugins/mp3_plugin.c mpd-mp3_plugin.o: inputPlugins/mp3_plugin.c
@AMDEP_TRUE@ source='inputPlugins/mp3_plugin.c' object='mpd-mp3_plugin.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ source='inputPlugins/mp3_plugin.c' object='mpd-mp3_plugin.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-mp3_plugin.Po' tmpdepfile='$(DEPDIR)/mpd-mp3_plugin.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-mp3_plugin.Po' tmpdepfile='$(DEPDIR)/mpd-mp3_plugin.TPo' @AMDEPBACKSLASH@
......
#ifndef ACK_H
#define ACK_H
#define ACK_ERROR_NOT_LIST 1
#define ACK_ERROR_ARG 2
#define ACK_ERROR_PASSWORD 3
#define ACK_ERROR_PERMISSION 4
#define ACK_ERROR_UNKNOWN 5
#define ACK_ERROR_NO_EXIST 6
#define ACK_ERROR_PLAYLIST_MAX 7
#define ACK_ERROR_SYSTEM 8
#define ACK_ERROR_PLAYLIST_LOAD 9
#define ACK_ERROR_UPDATE_ALREADY 10
#define ACK_ERROR_PLAYER_SYNC 11
#define ACK_ERROR_EXIST 12
#endif
...@@ -35,7 +35,7 @@ extern char * current_command; ...@@ -35,7 +35,7 @@ extern char * current_command;
extern int command_listNum; extern int command_listNum;
int proccessListOfCommands(FILE * fp, int * permission, int * expired, int proccessListOfCommands(FILE * fp, int * permission, int * expired,
List * list); int listOK, List * list);
int processCommand(FILE * fp, unsigned int * permission, char * commandString); int processCommand(FILE * fp, unsigned int * permission, char * commandString);
...@@ -54,7 +54,7 @@ void finishCommands(); ...@@ -54,7 +54,7 @@ void finishCommands();
current_command = NULL; \ current_command = NULL; \
} \ } \
else { \ else { \
myfprintf(fp, "ACK [%i@%i] " format "\n", \ myfprintf(stderr, "ACK [%i@%i] " format "\n", \
(int)error, command_listNum, \ (int)error, command_listNum, \
##__VA_ARGS__); \ ##__VA_ARGS__); \
} \ } \
......
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
#endif #endif
#endif #endif
char * conf_params[CONF_NUMBER_OF_PARAMS]; static char * conf_params[CONF_NUMBER_OF_PARAMS];
void initConf() { void initConf() {
int i; int i;
......
...@@ -112,17 +112,6 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) { ...@@ -112,17 +112,6 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
quitDecode(pc,dc); \ quitDecode(pc,dc); \
return; \ return; \
} \ } \
if(pc->metadataState == PLAYER_METADATA_STATE_WRITE && \
dc->metadataSet) \
{ \
memcpy(pc->metadata, dc->metadata, \
DECODE_METADATA_LENGTH); \
pc->metadata[DECODE_METADATA_LENGTH-1] = '\0'; \
pc->title = dc->title; \
pc->artist = dc->artist; \
pc->album = dc->album; \
} \
pc->metadataState = PLAYER_METADATA_STATE_READ; \
pc->totalTime = dc->totalTime; \ pc->totalTime = dc->totalTime; \
pc->sampleRate = dc->audioFormat.sampleRate; \ pc->sampleRate = dc->audioFormat.sampleRate; \
pc->bits = dc->audioFormat.bits; \ pc->bits = dc->audioFormat.bits; \
...@@ -184,7 +173,6 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, ...@@ -184,7 +173,6 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
stopDecode(dc); stopDecode(dc);
cb->begin = 0; cb->begin = 0;
cb->end = 0; cb->end = 0;
cb->wrap = 0;
dc->error = 0; dc->error = 0;
dc->start = 1; dc->start = 1;
waitOnDecode(pc,dc,cb,decodeWaitedOn); waitOnDecode(pc,dc,cb,decodeWaitedOn);
...@@ -271,11 +259,7 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { ...@@ -271,11 +259,7 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return; return;
} }
dc->metadataSet = 0; copyMpdTagToOutputBuffer(cb, NULL);
memset(dc->metadata, 0, DECODE_METADATA_LENGTH);
dc->title = -1;
dc->album = -1;
dc->artist = -1;
strncpy(dc->utf8url, pc->utf8url, MAXPATHLEN); strncpy(dc->utf8url, pc->utf8url, MAXPATHLEN);
dc->utf8url[MAXPATHLEN] = '\0'; dc->utf8url[MAXPATHLEN] = '\0';
...@@ -302,15 +286,18 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { ...@@ -302,15 +286,18 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return; return;
} }
if(inStream.metaTitle) { /*if(inStream.metaName) {
strncpy(dc->metadata, inStream.metaTitle, MpdTag * tag = newMpdTag();
DECODE_METADATA_LENGTH-1); tag->name = strdup(inStream.metaName);
dc->title = 0; copyMpdTagToOutputBuffer(cb, tag);
dc->metadataSet = 1; freeMpdTag(tag);
} }*/
/* reset Metadata in OutputBuffer */
ret = DECODE_ERROR_UNKTYPE; ret = DECODE_ERROR_UNKTYPE;
if(isRemoteUrl(dc->utf8url)) { if(isRemoteUrl(dc->utf8url)) {
cb->acceptMetadata = 1;
plugin = getInputPluginFromMimeType(inStream.mime); plugin = getInputPluginFromMimeType(inStream.mime);
if(plugin == NULL) { if(plugin == NULL) {
plugin = getInputPluginFromSuffix( plugin = getInputPluginFromSuffix(
...@@ -328,6 +315,7 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { ...@@ -328,6 +315,7 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
} }
} }
else { else {
cb->acceptMetadata = 0;
plugin = getInputPluginFromSuffix(getSuffix(dc->utf8url)); plugin = getInputPluginFromSuffix(getSuffix(dc->utf8url));
if(plugin && (plugin->streamTypes && INPUT_PLUGIN_STREAM_FILE)) if(plugin && (plugin->streamTypes && INPUT_PLUGIN_STREAM_FILE))
{ {
...@@ -399,6 +387,49 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { ...@@ -399,6 +387,49 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return 0; return 0;
} }
void handleMetadata(OutputBuffer * cb, PlayerControl * pc, int * previous,
int * currentChunkSent, MetadataChunk * currentChunk)
{
if(cb->begin!=cb->end) {
int meta = cb->metaChunk[cb->begin];
if( meta != *previous ) {
DEBUG("player: metadata change\n");
if( meta >= 0 && cb->metaChunkSet[meta]) {
DEBUG("player: new metadata from decoder!\n");
memcpy(currentChunk,
cb->metadataChunks+meta,
sizeof(MetadataChunk));
*currentChunkSent = 0;
cb->metaChunkSet[meta] = 0;
}
}
*previous = meta;
}
if(!(*currentChunkSent) && pc->metadataState ==
PLAYER_METADATA_STATE_WRITE)
{
*currentChunkSent = 1;
memcpy(&(pc->metadataChunk), currentChunk,
sizeof(MetadataChunk));
pc->metadataState = PLAYER_METADATA_STATE_READ;
kill(getppid(), SIGUSR1);
}
}
void advanceOutputBufferTo(OutputBuffer * cb, PlayerControl * pc,
int * previous, int * currentChunkSent, MetadataChunk * currentChunk,
int to)
{
while(cb->begin!=to) {
handleMetadata(cb, pc, previous, currentChunkSent,
currentChunk);
cb->begin++;
if(cb->begin>=buffered_chunks) {
cb->begin = 0;
}
}
}
void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
int pause = 0; int pause = 0;
int quit = 0; int quit = 0;
...@@ -411,6 +442,9 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -411,6 +442,9 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
int decodeWaitedOn = 0; int decodeWaitedOn = 0;
char silence[CHUNK_SIZE]; char silence[CHUNK_SIZE];
double sizeToTime = 0.0; double sizeToTime = 0.0;
int previousMetadataChunk = -1;
MetadataChunk currentMetadataChunk;
int currentChunkSent = 1;
memset(silence,0,CHUNK_SIZE); memset(silence,0,CHUNK_SIZE);
...@@ -420,7 +454,8 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -420,7 +454,8 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
pc->play = 0; pc->play = 0;
kill(getppid(),SIGUSR1); kill(getppid(),SIGUSR1);
while(*decode_pid>0 && !cb->wrap && cb->end-cb->begin<bbp && while(*decode_pid>0 && cb->end-cb->begin<bbp &&
cb->end!=buffered_chunks-1 &&
dc->state!=DECODE_STATE_STOP) dc->state!=DECODE_STATE_STOP)
{ {
processDecodeInput(); processDecodeInput();
...@@ -431,6 +466,8 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -431,6 +466,8 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
while(!quit) { while(!quit) {
processDecodeInput(); processDecodeInput();
handleDecodeStart(); handleDecodeStart();
handleMetadata(cb, pc, &previousMetadataChunk,
&currentChunkSent, &currentMetadataChunk);
if(dc->state==DECODE_STATE_STOP && if(dc->state==DECODE_STATE_STOP &&
pc->queueState==PLAYER_QUEUE_FULL && pc->queueState==PLAYER_QUEUE_FULL &&
pc->queueLockState==PLAYER_QUEUE_UNLOCKED) pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
...@@ -456,9 +493,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -456,9 +493,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
else doCrossFade = -1; else doCrossFade = -1;
} }
if(pause) my_usleep(10000); if(pause) my_usleep(10000);
else if((cb->begin!=cb->end || cb->wrap) && else if(cb->begin!=cb->end && cb->begin!=cb->next) {
cb->begin!=cb->next)
{
if(doCrossFade==1 && cb->next>=0 && if(doCrossFade==1 && cb->next>=0 &&
((cb->next>cb->begin && ((cb->next>cb->begin &&
(fadePosition=cb->next-cb->begin) (fadePosition=cb->next-cb->begin)
...@@ -471,7 +506,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -471,7 +506,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
crossFadeChunks = fadePosition; crossFadeChunks = fadePosition;
} }
test = cb->end; test = cb->end;
if(cb->wrap) test+=buffered_chunks; if(cb->end < cb->begin) test+=buffered_chunks;
nextChunk = cb->begin+crossFadeChunks; nextChunk = cb->begin+crossFadeChunks;
if(nextChunk<test) { if(nextChunk<test) {
if(nextChunk>=buffered_chunks) if(nextChunk>=buffered_chunks)
...@@ -521,20 +556,23 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -521,20 +556,23 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
cb->begin++; cb->begin++;
if(cb->begin>=buffered_chunks) { if(cb->begin>=buffered_chunks) {
cb->begin = 0; cb->begin = 0;
cb->wrap = 0;
} }
} }
else if(cb->next==cb->begin) { else if(cb->next==cb->begin) {
if(doCrossFade==1 && nextChunk>=0) { if(doCrossFade==1 && nextChunk>=0) {
nextChunk = cb->begin+crossFadeChunks; nextChunk = cb->begin+crossFadeChunks;
test = cb->end; test = cb->end;
if(cb->wrap) test+=buffered_chunks; if(cb->end < cb->begin) test+=buffered_chunks;
if(nextChunk<test) { if(nextChunk<test) {
if(nextChunk>=buffered_chunks) if(nextChunk>=buffered_chunks)
{ {
nextChunk -= buffered_chunks; nextChunk -= buffered_chunks;
} }
cb->begin = nextChunk; advanceOutputBufferTo(cb, pc,
&previousMetadataChunk,
&currentChunkSent,
&currentMetadataChunk,
nextChunk);
} }
} }
while(pc->queueState==PLAYER_QUEUE_DECODE || while(pc->queueState==PLAYER_QUEUE_DECODE ||
...@@ -589,9 +627,9 @@ void decode() { ...@@ -589,9 +627,9 @@ void decode() {
cb = &(getPlayerData()->buffer); cb = &(getPlayerData()->buffer);
clearAllMetaChunkSets(cb);
cb->begin = 0; cb->begin = 0;
cb->end = 0; cb->end = 0;
cb->wrap = 0;
pc = &(getPlayerData()->playerControl); pc = &(getPlayerData()->playerControl);
dc = &(getPlayerData()->decoderControl); dc = &(getPlayerData()->decoderControl);
dc->error = 0; dc->error = 0;
...@@ -606,31 +644,3 @@ void decode() { ...@@ -606,31 +644,3 @@ void decode() {
decodeParent(pc, dc, cb); decodeParent(pc, dc, cb);
} }
/* this is stuff for inputPlugins to use! */
#define copyStringToMetadata(string, element) { \
if(string && (slen = strlen(string)) && \
pos < DECODE_METADATA_LENGTH-1) \
{ \
strncpy(dc->metadata+pos, string, \
DECODE_METADATA_LENGTH-1-pos); \
element = pos; \
pos += slen+1; \
} \
}
void copyMpdTagToDecoderControlMetadata(DecoderControl * dc, MpdTag * tag) {
int pos = 0;
int slen;
if(dc->metadataSet) return;
if(!tag) return;
memset(dc->metadata, 0, DECODE_METADATA_LENGTH);
copyStringToMetadata(tag->title, dc->title);
copyStringToMetadata(tag->artist, dc->artist);
copyStringToMetadata(tag->album, dc->album);
dc->metadataSet = 1;
}
...@@ -46,8 +46,6 @@ ...@@ -46,8 +46,6 @@
#define DECODE_SUFFIX_MP4 5 #define DECODE_SUFFIX_MP4 5
#define DECODE_SUFFIX_WAVE 6 #define DECODE_SUFFIX_WAVE 6
#define DECODE_METADATA_LENGTH 4096
typedef struct _DecoderControl { typedef struct _DecoderControl {
volatile mpd_sint8 state; volatile mpd_sint8 state;
volatile mpd_sint8 stop; volatile mpd_sint8 stop;
...@@ -61,18 +59,11 @@ typedef struct _DecoderControl { ...@@ -61,18 +59,11 @@ typedef struct _DecoderControl {
AudioFormat audioFormat; AudioFormat audioFormat;
char utf8url[MAXPATHLEN+1]; char utf8url[MAXPATHLEN+1];
volatile float totalTime; volatile float totalTime;
volatile mpd_sint8 metadataSet;
char metadata[DECODE_METADATA_LENGTH];
volatile mpd_sint16 title;
volatile mpd_sint16 artist;
volatile mpd_sint16 album;
} DecoderControl; } DecoderControl;
void decodeSigHandler(int sig); void decodeSigHandler(int sig);
void decode(); void decode();
void copyMpdTagToDecoderControlMetadata(DecoderControl * dc, MpdTag * tag);
#endif #endif
/* vim:set shiftwidth=4 tabstop=8 expandtab: */ /* vim:set shiftwidth=4 tabstop=8 expandtab: */
...@@ -159,7 +159,7 @@ void readDirectoryDBIfUpdateIsFinished() { ...@@ -159,7 +159,7 @@ void readDirectoryDBIfUpdateIsFinished() {
if(directory_reReadDB && 0==directory_updatePid) { if(directory_reReadDB && 0==directory_updatePid) {
DEBUG("readDirectoryDB since update finished successfully\n"); DEBUG("readDirectoryDB since update finished successfully\n");
readDirectoryDB(); readDirectoryDB();
incrPlaylistVersion(); playlistVersionChange();
directory_reReadDB = 0; directory_reReadDB = 0;
} }
} }
......
...@@ -335,7 +335,7 @@ struct xing { ...@@ -335,7 +335,7 @@ struct xing {
long flags; /* valid fields (see below) */ long flags; /* valid fields (see below) */
unsigned long frames; /* total number of frames */ unsigned long frames; /* total number of frames */
unsigned long bytes; /* total number of bytes */ unsigned long bytes; /* total number of bytes */
unsigned char toc[100]; /* 100-point seek table */ unsigned char toc[100]; /* 100-point seek table */
long scale; /* ?? */ long scale; /* ?? */
}; };
...@@ -531,6 +531,18 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) { ...@@ -531,6 +531,18 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
default: default:
mad_synth_frame(&data->synth,&data->frame); mad_synth_frame(&data->synth,&data->frame);
if(data->inStream->metaTitle) {
MpdTag * tag = newMpdTag();
if(data->inStream->metaName) {
tag->name = strdup(data->inStream->metaName);
}
tag->title = strdup(data->inStream->metaTitle);
free(data->inStream->metaTitle);
data->inStream->metaTitle = NULL;
copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag);
}
for(i=0;i<(data->synth).pcm.length;i++) { for(i=0;i<(data->synth).pcm.length;i++) {
mpd_sint16 * sample; mpd_sint16 * sample;
...@@ -643,8 +655,33 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) { ...@@ -643,8 +655,33 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
dc->totalTime = data.totalTime; dc->totalTime = data.totalTime;
if(tag) { if(inStream->metaTitle) {
copyMpdTagToDecoderControlMetadata(dc, tag); if(tag) freeMpdTag(tag);
tag = newMpdTag();
tag->title = strdup(inStream->metaTitle);
/* free ths now, so we know we are done with it */
free(inStream->metaTitle);
inStream->metaTitle = NULL;
if(inStream->metaName) {
tag->name = strdup(inStream->metaName);
}
copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag);
}
else if(tag) {
if(inStream->metaName) {
if(tag->name) free(tag->name);
tag->name = strdup(inStream->metaName);
}
copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag);
}
else if(inStream->metaName) {
tag = newMpdTag();
if(inStream->metaName) {
tag->name = strdup(inStream->metaName);
}
copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag); freeMpdTag(tag);
} }
......
...@@ -200,17 +200,28 @@ MpdTag * oggCommentsParse(char ** comments) { ...@@ -200,17 +200,28 @@ MpdTag * oggCommentsParse(char ** comments) {
return ret; return ret;
} }
void putOggCommentsIntoDecoderControlMetadata(DecoderControl * dc, void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName,
char ** comments) char ** comments)
{ {
MpdTag * tag; MpdTag * tag;
if(dc->metadataSet) return;
tag = oggCommentsParse(comments); tag = oggCommentsParse(comments);
if(!tag && streamName) {
tag = newMpdTag();
}
if(!tag) return; if(!tag) return;
copyMpdTagToDecoderControlMetadata(dc, tag); /*if(tag->artist) printf("Artist: %s\n", tag->artist);
if(tag->album) printf("Album: %s\n", tag->album);
if(tag->track) printf("Track: %s\n", tag->track);
if(tag->title) printf("Title: %s\n", tag->title);*/
if(streamName) {
if(tag->name) free(tag->name);
tag->name = strdup(streamName);
}
copyMpdTagToOutputBuffer(cb, tag);
freeMpdTag(tag); freeMpdTag(tag);
} }
...@@ -221,6 +232,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) ...@@ -221,6 +232,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
ov_callbacks callbacks; ov_callbacks callbacks;
OggCallbackData data; OggCallbackData data;
int current_section; int current_section;
int prev_section = -1;
int eof = 0; int eof = 0;
long ret; long ret;
#define OGG_CHUNK_SIZE 4096 #define OGG_CHUNK_SIZE 4096
...@@ -228,7 +240,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) ...@@ -228,7 +240,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
int chunkpos = 0; int chunkpos = 0;
long bitRate = 0; long bitRate = 0;
long test; long test;
float replayGainScale; float replayGainScale = 1.0;
char ** comments; char ** comments;
data.inStream = inStream; data.inStream = inStream;
...@@ -252,24 +264,10 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) ...@@ -252,24 +264,10 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
return 0; return 0;
} }
{
vorbis_info *vi=ov_info(&vf,-1);
dc->audioFormat.bits = 16;
dc->audioFormat.channels = vi->channels;
dc->audioFormat.sampleRate = vi->rate;
getOutputAudioFormat(&(dc->audioFormat),&(cb->audioFormat));
}
dc->totalTime = ov_time_total(&vf,-1); dc->totalTime = ov_time_total(&vf,-1);
if(dc->totalTime < 0) dc->totalTime = 0; if(dc->totalTime < 0) dc->totalTime = 0;
comments = ov_comment(&vf, -1)->user_comments; dc->audioFormat.bits = 16;
putOggCommentsIntoDecoderControlMetadata(dc, comments);
dc->state = DECODE_STATE_DECODE;
replayGainScale = ogg_getReplayGainScale(comments);
while(!eof) { while(!eof) {
if(dc->seek) { if(dc->seek) {
...@@ -285,6 +283,24 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) ...@@ -285,6 +283,24 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
OGG_DECODE_USE_BIGENDIAN, OGG_DECODE_USE_BIGENDIAN,
2, 1, &current_section); 2, 1, &current_section);
if(current_section!=prev_section) {
/*printf("new song!\n");*/
vorbis_info *vi=ov_info(&vf,-1);
dc->audioFormat.channels = vi->channels;
dc->audioFormat.sampleRate = vi->rate;
if(dc->state == DECODE_STATE_START) {
getOutputAudioFormat(&(dc->audioFormat),
&(cb->audioFormat));
dc->state = DECODE_STATE_DECODE;
}
comments = ov_comment(&vf, -1)->user_comments;
putOggCommentsIntoOutputBuffer(cb, inStream->metaName,
comments);
replayGainScale = ogg_getReplayGainScale(comments);
}
prev_section = current_section;
if(ret <= 0 && ret != OV_HOLE) { if(ret <= 0 && ret != OV_HOLE) {
eof = 1; eof = 1;
break; break;
......
...@@ -26,6 +26,14 @@ ...@@ -26,6 +26,14 @@
#include <unistd.h> #include <unistd.h>
int openInputStream(InputStream * inStream, char * url) { int openInputStream(InputStream * inStream, char * url) {
inStream->offset = 0;
inStream->size = 0;
inStream->error = 0;
inStream->mime = NULL;
inStream->seekable = 0;
inStream->metaName = NULL;
inStream->metaTitle = NULL;
if(inputStream_fileOpen(inStream,url) == 0) return 0; if(inputStream_fileOpen(inStream,url) == 0) return 0;
if(inputStream_httpOpen(inStream,url) == 0) return 0; if(inputStream_httpOpen(inStream,url) == 0) return 0;
...@@ -43,6 +51,10 @@ size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size, ...@@ -43,6 +51,10 @@ size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size,
} }
int closeInputStream(InputStream * inStream) { int closeInputStream(InputStream * inStream) {
if(inStream->mime) free(inStream->mime);
if(inStream->metaName) free(inStream->metaName);
if(inStream->metaTitle) free(inStream->metaTitle);
return inStream->closeFunc(inStream); return inStream->closeFunc(inStream);
} }
...@@ -53,4 +65,3 @@ int inputStreamAtEOF(InputStream * inStream) { ...@@ -53,4 +65,3 @@ int inputStreamAtEOF(InputStream * inStream) {
int bufferInputStream(InputStream * inStream) { int bufferInputStream(InputStream * inStream) {
return inStream->bufferFunc(inStream); return inStream->bufferFunc(inStream);
} }
/* vim:set shiftwidth=8 tabstop=8 expandtab: */
...@@ -45,6 +45,7 @@ struct _InputStream { ...@@ -45,6 +45,7 @@ struct _InputStream {
InputStreamAtEOFFunc atEOFFunc; InputStreamAtEOFFunc atEOFFunc;
InputStreamBufferFunc bufferFunc; InputStreamBufferFunc bufferFunc;
void * data; void * data;
char * metaName;
char * metaTitle; char * metaTitle;
}; };
......
...@@ -32,10 +32,7 @@ int inputStream_fileOpen(InputStream * inStream, char * filename) { ...@@ -32,10 +32,7 @@ int inputStream_fileOpen(InputStream * inStream, char * filename) {
return -1; return -1;
} }
inStream->offset = 0;
inStream->seekable = 1; inStream->seekable = 1;
inStream->mime = NULL;
inStream->metaTitle = NULL;
fseek(fp,0,SEEK_END); fseek(fp,0,SEEK_END);
inStream->size = ftell(fp); inStream->size = ftell(fp);
......
...@@ -57,6 +57,7 @@ typedef struct _InputStreemHTTPData { ...@@ -57,6 +57,7 @@ typedef struct _InputStreemHTTPData {
int timesRedirected; int timesRedirected;
int icyMetaint; int icyMetaint;
int prebuffer; int prebuffer;
int icyOffset;
} InputStreamHTTPData; } InputStreamHTTPData;
static InputStreamHTTPData * newInputStreamHTTPData() { static InputStreamHTTPData * newInputStreamHTTPData() {
...@@ -69,6 +70,7 @@ static InputStreamHTTPData * newInputStreamHTTPData() { ...@@ -69,6 +70,7 @@ static InputStreamHTTPData * newInputStreamHTTPData() {
ret->timesRedirected = 0; ret->timesRedirected = 0;
ret->icyMetaint = 0; ret->icyMetaint = 0;
ret->prebuffer = 0; ret->prebuffer = 0;
ret->icyOffset = 0;
return ret; return ret;
} }
...@@ -231,7 +233,7 @@ static int finishHTTPInit(InputStream * inStream) { ...@@ -231,7 +233,7 @@ static int finishHTTPInit(InputStream * inStream) {
"Connection: close\r\n" "Connection: close\r\n"
"User-Agent: %s/%s\r\n" "User-Agent: %s/%s\r\n"
"Range: bytes=%ld-\r\n" "Range: bytes=%ld-\r\n"
/*"Icy-Metadata:1\r\n"*/ "Icy-Metadata:1\r\n"
"\r\n", "\r\n",
data->path, data->host, "httpTest", "0.0.0", data->path, data->host, "httpTest", "0.0.0",
inStream->offset); inStream->offset);
...@@ -372,20 +374,24 @@ static int getHTTPHello(InputStream * inStream) { ...@@ -372,20 +374,24 @@ static int getHTTPHello(InputStream * inStream) {
char * temp = strstr(cur+incr,"\r\n"); char * temp = strstr(cur+incr,"\r\n");
if(!temp) break; if(!temp) break;
*temp = '\0'; *temp = '\0';
if(inStream->metaTitle) free(inStream->metaTitle); if(inStream->metaName) free(inStream->metaName);
while(*(incr+cur) == ' ') incr++; while(*(incr+cur) == ' ') incr++;
inStream->metaTitle = strdup(cur+incr); inStream->metaName = strdup(cur+incr);
*temp = '\r'; *temp = '\r';
DEBUG("inputStream_http: metaName: %s\n",
inStream->metaName);
} }
else if(0 == strncmp(cur, "\r\nx-audiocast-name:", 19)) { else if(0 == strncmp(cur, "\r\nx-audiocast-name:", 19)) {
int incr = 19; int incr = 19;
char * temp = strstr(cur+incr,"\r\n"); char * temp = strstr(cur+incr,"\r\n");
if(!temp) break; if(!temp) break;
*temp = '\0'; *temp = '\0';
if(inStream->metaTitle) free(inStream->metaTitle); if(inStream->metaName) free(inStream->metaName);
while(*(incr+cur) == ' ') incr++; while(*(incr+cur) == ' ') incr++;
inStream->metaTitle = strdup(cur+incr); inStream->metaName = strdup(cur+incr);
*temp = '\r'; *temp = '\r';
DEBUG("inputStream_http: metaName: %s\n",
inStream->metaName);
} }
else if(0 == strncmp(cur, "\r\nContent-Type:", 15)) { else if(0 == strncmp(cur, "\r\nContent-Type:", 15)) {
int incr = 15; int incr = 15;
...@@ -439,13 +445,6 @@ int inputStream_httpOpen(InputStream * inStream, char * url) { ...@@ -439,13 +445,6 @@ int inputStream_httpOpen(InputStream * inStream, char * url) {
inStream->atEOFFunc = inputStream_httpAtEOF; inStream->atEOFFunc = inputStream_httpAtEOF;
inStream->bufferFunc = inputStream_httpBuffer; inStream->bufferFunc = inputStream_httpBuffer;
inStream->offset = 0;
inStream->size = 0;
inStream->error = 0;
inStream->mime = NULL;
inStream->seekable = 0;
inStream->metaTitle = NULL;
return 0; return 0;
} }
...@@ -453,32 +452,89 @@ int inputStream_httpSeek(InputStream * inStream, long offset, int whence) { ...@@ -453,32 +452,89 @@ int inputStream_httpSeek(InputStream * inStream, long offset, int whence) {
return -1; return -1;
} }
static void parseIcyMetadata(InputStream * inStream, char * metadata,
int size)
{
char * r;
char * s;
char * temp = malloc(size+1);
memcpy(temp, metadata, size);
temp[size] = '\0';
s = strtok_r(temp, ";", &r);
while(s) {
if(0 == strncmp(s, "StreamTitle=", 12)) {
int cur = 12;
if(inStream->metaTitle) free(inStream->metaTitle);
if(*(s+cur) == '\'') cur++;
if(s[strlen(s)-1] == '\'') {
s[strlen(s)-1] = '\0';
}
inStream->metaTitle = strdup(s+cur);
DEBUG("inputStream_http: metaTitle: %s\n",
inStream->metaTitle);
}
s = strtok_r(NULL, ";", &r);
}
free(temp);
}
size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size, size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size,
size_t nmemb) size_t nmemb)
{ {
InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data; InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
long tosend = 0; long tosend = 0;
long inlen = size*nmemb; long inlen = size*nmemb;
long maxToSend = data->buflen;
inputStream_httpBuffer(inStream); inputStream_httpBuffer(inStream);
switch(data->connState) { switch(data->connState) {
case HTTP_CONN_STATE_OPEN: case HTTP_CONN_STATE_OPEN:
if(data->prebuffer || data->buflen < data->icyMetaint) return 0;
break;
case HTTP_CONN_STATE_CLOSED: case HTTP_CONN_STATE_CLOSED:
break; if(data->buflen) break;
default: default:
return 0; return 0;
} }
if(data->prebuffer) return 0; if(data->icyMetaint > 0) {
if(data->icyOffset >= data->icyMetaint) {
int metalen = *(data->buffer);
metalen <<= 4;
if(metalen < 0) metalen = 0;
if(metalen+1 > data->buflen) {
/* damn that's some fucking big metadata! */
if(HTTP_BUFFER_SIZE < metalen+1) {
data->connState =
HTTP_CONN_STATE_CLOSED;
close(data->sock);
data->buflen = 0;
}
return 0;
}
if(metalen > 0) {
parseIcyMetadata(inStream, data->buffer+1,
metalen);
}
data->buflen -= metalen+1;
memmove(data->buffer, data->buffer+metalen+1,
data->buflen);
data->icyOffset = 0;
}
maxToSend = data->icyMetaint-data->icyOffset;
maxToSend = maxToSend > data->buflen ? data->buflen : maxToSend;
}
if(data->buflen > 0) { if(data->buflen > 0) {
tosend = inlen > data->buflen ? data->buflen : inlen; tosend = inlen > maxToSend ? maxToSend : inlen;
tosend = (tosend/size)*size; tosend = (tosend/size)*size;
memcpy(ptr, data->buffer, tosend); memcpy(ptr, data->buffer, tosend);
/*fwrite(ptr,1,readed,stdout);*/ /*fwrite(ptr,1,readed,stdout);*/
data->buflen -= tosend; data->buflen -= tosend;
data->icyOffset+= tosend;
/*fwrite(data->buffer,1,readed,stdout);*/ /*fwrite(data->buffer,1,readed,stdout);*/
memmove(data->buffer, data->buffer+tosend, data->buflen); memmove(data->buffer, data->buffer+tosend, data->buflen);
...@@ -498,7 +554,6 @@ int inputStream_httpClose(InputStream * inStream) { ...@@ -498,7 +554,6 @@ int inputStream_httpClose(InputStream * inStream) {
close(data->sock); close(data->sock);
} }
if(inStream->mime) free(inStream->mime);
freeInputStreamHTTPData(data); freeInputStreamHTTPData(data);
return 0; return 0;
...@@ -538,7 +593,9 @@ int inputStream_httpBuffer(InputStream * inStream) { ...@@ -538,7 +593,9 @@ int inputStream_httpBuffer(InputStream * inStream) {
return -1; return -1;
} }
if(data->buflen == 0) data->prebuffer = 1; if(data->buflen == 0 || data->buflen < data->icyMetaint) {
data->prebuffer = 1;
}
else if(data->buflen > HTTP_PREBUFFER_SIZE) data->prebuffer = 0; else if(data->buflen > HTTP_PREBUFFER_SIZE) data->prebuffer = 0;
if(data->connState == HTTP_CONN_STATE_OPEN && if(data->connState == HTTP_CONN_STATE_OPEN &&
...@@ -563,4 +620,3 @@ int inputStream_httpBuffer(InputStream * inStream) { ...@@ -563,4 +620,3 @@ int inputStream_httpBuffer(InputStream * inStream) {
return (readed ? 1 : 0); return (readed ? 1 : 0);
} }
/* vim:set shiftwidth=8 tabstop=8 expandtab: */
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#define INTERFACE_MAX_BUFFER_LENGTH MAXPATHLEN+1024 #define INTERFACE_MAX_BUFFER_LENGTH MAXPATHLEN+1024
#define INTERFACE_LIST_MODE_BEGIN "command_list_begin" #define INTERFACE_LIST_MODE_BEGIN "command_list_begin"
#define INTERFACE_LIST_OK_MODE_BEGIN "command_list_ok_begin"
#define INTERFACE_LIST_MODE_END "command_list_end" #define INTERFACE_LIST_MODE_END "command_list_end"
#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096 #define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096
...@@ -62,6 +63,7 @@ typedef struct _Interface { ...@@ -62,6 +63,7 @@ typedef struct _Interface {
unsigned int permission; unsigned int permission;
time_t lastTime; time_t lastTime;
List * commandList; /* for when in list mode */ List * commandList; /* for when in list mode */
int commandListOK; /* print OK after each command execution */
unsigned long long commandListSize; /* mem commandList consumes */ unsigned long long commandListSize; /* mem commandList consumes */
List * bufferList; /* for output if client is slow */ List * bufferList; /* for output if client is slow */
unsigned long long outputBufferSize; /* mem bufferList consumes */ unsigned long long outputBufferSize; /* mem bufferList consumes */
...@@ -230,6 +232,7 @@ int interfaceReadInput(Interface * interface) { ...@@ -230,6 +232,7 @@ int interfaceReadInput(Interface * interface) {
interface->fp, interface->fp,
&(interface->permission), &(interface->permission),
&(interface->expired), &(interface->expired),
interface->commandListOK,
interface->commandList); interface->commandList);
DEBUG("interface %i: process command " DEBUG("interface %i: process command "
"list returned %i\n", "list returned %i\n",
...@@ -281,27 +284,27 @@ int interfaceReadInput(Interface * interface) { ...@@ -281,27 +284,27 @@ int interfaceReadInput(Interface * interface) {
interface->commandList = makeList(free); interface->commandList = makeList(free);
interface->commandListSize = interface->commandListSize =
sizeof(List); sizeof(List);
interface->commandListOK = 0;
ret = 1;
}
else if(strcmp(interface->buffer,
INTERFACE_LIST_OK_MODE_BEGIN)
==0)
{
interface->commandList = makeList(free);
interface->commandListSize =
sizeof(List);
interface->commandListOK = 1;
ret = 1; ret = 1;
} }
else { else {
if(strcmp(interface->buffer, DEBUG("interface %i: process command \"%s\"\n",interface->num,interface->buffer);
INTERFACE_LIST_MODE_END) ret = processCommand(
==0)
{
commandError(interface->fp,
ACK_ERROR_NOT_LIST,
"not in command list mode");
ret = -1;
}
else {
DEBUG("interface %i: process command \"%s\"\n",interface->num,interface->buffer);
ret = processCommand(
interface->fp, interface->fp,
&(interface-> &(interface->
permission), permission),
interface->buffer); interface->buffer);
DEBUG("interface %i: command returned %i\n",interface->num,ret); DEBUG("interface %i: command returned %i\n",interface->num,ret);
}
if(ret==0) { if(ret==0) {
commandSuccess(interface->fp); commandSuccess(interface->fp);
} }
...@@ -648,4 +651,3 @@ void printInterfaceOutBuffer(Interface * interface) { ...@@ -648,4 +651,3 @@ void printInterfaceOutBuffer(Interface * interface) {
interface->outBuflen = 0; interface->outBuflen = 0;
} }
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
...@@ -87,7 +87,7 @@ void usage(char * argv[]) { ...@@ -87,7 +87,7 @@ void usage(char * argv[]) {
void version() { void version() {
LOG("mpd (MPD: Music Player Daemon) %s\n",VERSION); LOG("mpd (MPD: Music Player Daemon) %s\n",VERSION);
LOG("\n"); LOG("\n");
LOG("Copyright (C) 2003 Warren Dukes <shank@mercury.chem.pitt.edu>\n"); LOG("Copyright (C) 2003-2004 Warren Dukes <shank@mercury.chem.pitt.edu>\n");
LOG("This is free software; see the source for copying conditions. There is NO\n"); LOG("This is free software; see the source for copying conditions. There is NO\n");
LOG("warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); LOG("warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
LOG("\n"); LOG("\n");
...@@ -224,7 +224,7 @@ void establishListen(Options * options) { ...@@ -224,7 +224,7 @@ void establishListen(Options * options) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(!options->createDB && !options->updateDB && if(options->createDB <= 0 && !options->updateDB &&
(listenSocket = establish(port))<0) (listenSocket = establish(port))<0)
{ {
ERROR("error binding port\n"); ERROR("error binding port\n");
......
#include "metadataChunk.h"
#include <string.h>
void initMetadataChunk(MetadataChunk * chunk) {
memset(chunk, 0, sizeof(MetadataChunk));
chunk->name = -1;
chunk->artist = -1;
chunk->album = -1;
chunk->title = -1;
}
#define dupElementToTag(string, element) { \
if(element >= 0 && element < METADATA_BUFFER_LENGTH) { \
string = strdup(chunk->buffer+element); \
} \
}
MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk) {
MpdTag * ret = newMpdTag();
chunk->buffer[METADATA_BUFFER_LENGTH] = '\0';
dupElementToTag(ret->name, chunk->name);
dupElementToTag(ret->title, chunk->title);
dupElementToTag(ret->artist, chunk->artist);
dupElementToTag(ret->album, chunk->album);
return ret;
}
#define copyStringToChunk(string, element) { \
if(string && (slen = strlen(string)) && \
pos < METADATA_BUFFER_LENGTH-1) \
{ \
strncpy(chunk->buffer+pos, string, \
METADATA_BUFFER_LENGTH-1-pos); \
element = pos; \
pos += slen+1; \
} \
}
void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk) {
int pos = 0;
int slen;
initMetadataChunk(chunk);
copyStringToChunk(tag->name, chunk->name);
copyStringToChunk(tag->title, chunk->title);
copyStringToChunk(tag->artist, chunk->artist);
copyStringToChunk(tag->album, chunk->album);
}
#ifndef METADATA_CHUNK_H
#define METADATA_CHUNK_H
#define METADATA_BUFFER_LENGTH 1024
#include "tag.h"
typedef struct _MetadataChunk {
int name;
int title;
int artist;
int album;
char buffer[METADATA_BUFFER_LENGTH];
} MetadataChunk;
void initMetadataChunk(MetadataChunk *);
MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk);
void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk);
#endif
...@@ -21,15 +21,38 @@ ...@@ -21,15 +21,38 @@
#include "pcm_utils.h" #include "pcm_utils.h"
#include "playerData.h" #include "playerData.h"
#include "utils.h" #include "utils.h"
#include "log.h"
#include <string.h> #include <string.h>
static mpd_sint16 currentChunk = -1; static mpd_sint16 currentChunk = -1;
static mpd_sint8 currentMetaChunk = -1;
static mpd_sint8 sendMetaChunk = 0;
void clearAllMetaChunkSets(OutputBuffer * cb) {
int i;
for(i=0; i<BUFFERED_METACHUNKS; i++) {
cb->metaChunkSet[i] = 0;
}
}
void clearOutputBuffer(OutputBuffer * cb) { void clearOutputBuffer(OutputBuffer * cb) {
int currentSet = 1;
currentChunk = -1; currentChunk = -1;
cb->end = cb->begin; cb->end = cb->begin;
cb->wrap = 0;
/* be sure to reset metaChunkSets cause we are skipping over audio
* audio chunks, and thus skipping over metadata */
if(sendMetaChunk == 0 && currentMetaChunk >= 0) {
currentSet = cb->metaChunkSet[currentChunk];
}
clearAllMetaChunkSets(cb);
if(sendMetaChunk == 0 && currentMetaChunk >= 0) {
cb->metaChunkSet[currentChunk] = currentSet;
}
} }
void flushOutputBuffer(OutputBuffer * cb) { void flushOutputBuffer(OutputBuffer * cb) {
...@@ -37,7 +60,6 @@ void flushOutputBuffer(OutputBuffer * cb) { ...@@ -37,7 +60,6 @@ void flushOutputBuffer(OutputBuffer * cb) {
cb->end++; cb->end++;
if(cb->end>=buffered_chunks) { if(cb->end>=buffered_chunks) {
cb->end = 0; cb->end = 0;
cb->wrap = 1;
} }
currentChunk = -1; currentChunk = -1;
} }
...@@ -74,8 +96,11 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, ...@@ -74,8 +96,11 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
while(datalen) { while(datalen) {
if(currentChunk != cb->end) { if(currentChunk != cb->end) {
while(cb->begin==cb->end && cb->wrap && !dc->stop) int next = cb->end+1;
{ if(next>=buffered_chunks) {
next = 0;
}
while(cb->begin==next && !dc->stop) {
if(dc->seek) { if(dc->seek) {
if(seekable) { if(seekable) {
return OUTPUT_BUFFER_DC_SEEK; return OUTPUT_BUFFER_DC_SEEK;
...@@ -95,6 +120,13 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, ...@@ -95,6 +120,13 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
currentChunk = cb->end; currentChunk = cb->end;
cb->chunkSize[currentChunk] = 0; cb->chunkSize[currentChunk] = 0;
if(sendMetaChunk) {
cb->metaChunk[currentChunk] = currentMetaChunk;
}
else cb->metaChunk[currentChunk] = -1;
cb->bitRate[currentChunk] = bitRate;
cb->times[currentChunk] = time;
} }
chunkLeft = CHUNK_SIZE-cb->chunkSize[currentChunk]; chunkLeft = CHUNK_SIZE-cb->chunkSize[currentChunk];
...@@ -104,9 +136,6 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, ...@@ -104,9 +136,6 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
cb->chunkSize[currentChunk], cb->chunkSize[currentChunk],
data, dataToSend); data, dataToSend);
cb->chunkSize[currentChunk]+= dataToSend; cb->chunkSize[currentChunk]+= dataToSend;
cb->bitRate[currentChunk] = bitRate;
cb->times[currentChunk] = time;
datalen-= dataToSend; datalen-= dataToSend;
data+= dataToSend; data+= dataToSend;
...@@ -117,4 +146,46 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, ...@@ -117,4 +146,46 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
return 0; return 0;
} }
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag) {
int nextChunk;
static MpdTag * last = NULL;
if(!cb->acceptMetadata || !tag) {
sendMetaChunk = 0;
if(last) free(last);
last = NULL;
DEBUG("copyMpdTagToOB: !acceptMetadata || !tag\n");
return 0;
}
if(last && mpdTagsAreEqual(last, tag)) {
DEBUG("copyMpdTagToOB: same as last\n");
return 0;
}
if(last) freeMpdTag(last);
last = NULL;
nextChunk = currentMetaChunk+1;
if(nextChunk >= BUFFERED_METACHUNKS) nextChunk = 0;
if(cb->metaChunkSet[nextChunk]) {
sendMetaChunk = 0;
DEBUG("copyMpdTagToOB: metachunk in use!\n");
return -1;
}
sendMetaChunk = 1;
currentMetaChunk = nextChunk;
last = mpdTagDup(tag);
copyMpdTagToMetadataChunk(tag, &(cb->metadataChunks[currentMetaChunk]));
cb->metaChunkSet[nextChunk] = 1;
DEBUG("copyMpdTagToOB: copiedTag\n");
return 0;
}
...@@ -23,10 +23,13 @@ ...@@ -23,10 +23,13 @@
#include "decode.h" #include "decode.h"
#include "audio.h" #include "audio.h"
#include "inputStream.h" #include "inputStream.h"
#include "metadataChunk.h"
#define OUTPUT_BUFFER_DC_STOP -1 #define OUTPUT_BUFFER_DC_STOP -1
#define OUTPUT_BUFFER_DC_SEEK -2 #define OUTPUT_BUFFER_DC_SEEK -2
#define BUFFERED_METACHUNKS 25
typedef struct _OutputBuffer { typedef struct _OutputBuffer {
char * volatile chunks; char * volatile chunks;
mpd_uint16 * volatile chunkSize; mpd_uint16 * volatile chunkSize;
...@@ -35,8 +38,11 @@ typedef struct _OutputBuffer { ...@@ -35,8 +38,11 @@ typedef struct _OutputBuffer {
mpd_sint16 volatile begin; mpd_sint16 volatile begin;
mpd_sint16 volatile end; mpd_sint16 volatile end;
mpd_sint16 volatile next; mpd_sint16 volatile next;
mpd_sint8 volatile wrap;
AudioFormat audioFormat; AudioFormat audioFormat;
MetadataChunk metadataChunks[BUFFERED_METACHUNKS];
mpd_sint8 metaChunkSet[BUFFERED_METACHUNKS];
mpd_sint8 * volatile metaChunk;
volatile mpd_sint8 acceptMetadata;
} OutputBuffer; } OutputBuffer;
void clearOutputBuffer(OutputBuffer * cb); void clearOutputBuffer(OutputBuffer * cb);
...@@ -49,5 +55,8 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, ...@@ -49,5 +55,8 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
DecoderControl * dc, int seekable, char * data, long datalen, DecoderControl * dc, int seekable, char * data, long datalen,
float time, mpd_uint16 bitRate); float time, mpd_uint16 bitRate);
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag);
void clearAllMetaChunkSets(OutputBuffer * cb);
#endif #endif
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
...@@ -281,5 +281,3 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, ...@@ -281,5 +281,3 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat,
return outSize; return outSize;
} }
/* vim:set shiftwidth=8 tabstop=8 expandtab: */
...@@ -55,9 +55,6 @@ static void resetPlayerMetadata() { ...@@ -55,9 +55,6 @@ static void resetPlayerMetadata() {
if(pc->metadataState == PLAYER_METADATA_STATE_READ) { if(pc->metadataState == PLAYER_METADATA_STATE_READ) {
pc->metadataState = PLAYER_METADATA_STATE_WRITE; pc->metadataState = PLAYER_METADATA_STATE_WRITE;
pc->title = -1;
pc->artist = -1;
pc->album = -1;
} }
} }
...@@ -75,8 +72,6 @@ void resetPlayer() { ...@@ -75,8 +72,6 @@ void resetPlayer() {
getPlayerData()->playerControl.seek = 0; getPlayerData()->playerControl.seek = 0;
getPlayerData()->playerControl.metadataState = getPlayerData()->playerControl.metadataState =
PLAYER_METADATA_STATE_WRITE; PLAYER_METADATA_STATE_WRITE;
getPlayerData()->playerControl.title = -1;
/* kill decode process if it got left running */
pid = getPlayerData()->playerControl.decode_pid; pid = getPlayerData()->playerControl.decode_pid;
if(pid>0) kill(pid,SIGTERM); if(pid>0) kill(pid,SIGTERM);
getPlayerData()->playerControl.decode_pid = 0; getPlayerData()->playerControl.decode_pid = 0;
...@@ -474,31 +469,24 @@ void playerCycleLogFiles() { ...@@ -474,31 +469,24 @@ void playerCycleLogFiles() {
/* this actually creates a dupe of the current metadata */ /* this actually creates a dupe of the current metadata */
Song * playerCurrentDecodeSong() { Song * playerCurrentDecodeSong() {
static Song * song = NULL; static Song * song = NULL;
static MetadataChunk * prev = NULL;
Song * ret = NULL;
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
if(pc->metadataState == PLAYER_METADATA_STATE_READ && if(pc->metadataState == PLAYER_METADATA_STATE_READ) {
(!song || strcmp(song->utf8url, pc->currentUrl))) DEBUG("playerCurrentDecodeSong: caught new metadata!\n");
{ if(prev) free(prev);
prev = malloc(sizeof(MetadataChunk));
memcpy(prev, &(pc->metadataChunk), sizeof(MetadataChunk));
if(song) freeJustSong(song); if(song) freeJustSong(song);
song = newNullSong(); song = newNullSong();
song->tag = newMpdTag();
if(song->utf8url) free(song->utf8url); if(song->utf8url) free(song->utf8url);
song->utf8url = strdup(pc->currentUrl); song->utf8url = strdup(pc->currentUrl);
if(pc->title >= 0) { song->tag = metadataChunkToMpdTagDup(prev);
song->tag->title = strdup(pc->title + pc->metadata);
}
if(pc->artist >= 0) {
song->tag->artist = strdup(pc->artist + pc->metadata);
}
if(pc->album >= 0) {
song->tag->album = strdup(pc->album + pc->metadata);
}
validateUtf8Tag(song->tag); validateUtf8Tag(song->tag);
resetPlayerMetadata(); ret = song;
return song; resetPlayerMetadata();
} }
return NULL; return ret;
} }
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "decode.h" #include "decode.h"
#include "mpd_types.h" #include "mpd_types.h"
#include "song.h" #include "song.h"
#include "metadataChunk.h"
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> #include <sys/param.h>
...@@ -84,10 +85,7 @@ typedef struct _PlayerControl { ...@@ -84,10 +85,7 @@ typedef struct _PlayerControl {
volatile int decode_pid; volatile int decode_pid;
volatile mpd_sint8 cycleLogFiles; volatile mpd_sint8 cycleLogFiles;
volatile mpd_sint8 metadataState; volatile mpd_sint8 metadataState;
char metadata[DECODE_METADATA_LENGTH]; MetadataChunk metadataChunk;
volatile mpd_sint16 title;
volatile mpd_sint16 artist;
volatile mpd_sint16 album;
} PlayerControl; } PlayerControl;
void clearPlayerPid(); void clearPlayerPid();
...@@ -157,4 +155,3 @@ void playerCycleLogFiles(); ...@@ -157,4 +155,3 @@ void playerCycleLogFiles();
Song * playerCurrentDecodeSong(); Song * playerCurrentDecodeSong();
#endif #endif
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
...@@ -73,6 +73,7 @@ void initPlayerData() { ...@@ -73,6 +73,7 @@ void initPlayerData() {
allocationSize+= buffered_chunks*sizeof(float); /*for times*/ allocationSize+= buffered_chunks*sizeof(float); /*for times*/
allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for chunkSize*/ allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for chunkSize*/
allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for bitRate*/ allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for bitRate*/
allocationSize+= buffered_chunks*sizeof(mpd_sint8); /*for metaChunk*/
allocationSize+= sizeof(PlayerData); /*for playerData struct*/ allocationSize+= sizeof(PlayerData); /*for playerData struct*/
if((shmid = shmget(IPC_PRIVATE,allocationSize,IPC_CREAT|0600))<0) { if((shmid = shmget(IPC_PRIVATE,allocationSize,IPC_CREAT|0600))<0) {
...@@ -95,8 +96,10 @@ void initPlayerData() { ...@@ -95,8 +96,10 @@ void initPlayerData() {
buffered_chunks*CHUNK_SIZE); buffered_chunks*CHUNK_SIZE);
buffer->bitRate = (mpd_uint16 *)(((char *)buffer->chunkSize)+ buffer->bitRate = (mpd_uint16 *)(((char *)buffer->chunkSize)+
buffered_chunks*sizeof(mpd_sint16)); buffered_chunks*sizeof(mpd_sint16));
buffer->times = (float *)(((char *)buffer->bitRate)+ buffer->metaChunk = (mpd_sint8 *)(((char *)buffer->bitRate)+
buffered_chunks*sizeof(mpd_sint16)); buffered_chunks*sizeof(mpd_sint16));
buffer->times = (float *)(((char *)buffer->metaChunk)+
buffered_chunks*sizeof(mpd_sint8));
playerData_pd->playerControl.stop = 0; playerData_pd->playerControl.stop = 0;
playerData_pd->playerControl.pause = 0; playerData_pd->playerControl.pause = 0;
...@@ -111,15 +114,10 @@ void initPlayerData() { ...@@ -111,15 +114,10 @@ void initPlayerData() {
memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN+1); memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN+1);
memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN+1); memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN+1);
memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN+1); memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN+1);
memset(playerData_pd->playerControl.metadata, 0,
DECODE_METADATA_LENGTH);
playerData_pd->playerControl.crossFade = crossfade; playerData_pd->playerControl.crossFade = crossfade;
playerData_pd->playerControl.softwareVolume = 1000; playerData_pd->playerControl.softwareVolume = 1000;
playerData_pd->playerControl.totalPlayTime = 0; playerData_pd->playerControl.totalPlayTime = 0;
playerData_pd->playerControl.decode_pid = 0; playerData_pd->playerControl.decode_pid = 0;
playerData_pd->playerControl.title = -1;
playerData_pd->playerControl.artist = -1;
playerData_pd->playerControl.album = -1;
playerData_pd->playerControl.metadataState = playerData_pd->playerControl.metadataState =
PLAYER_METADATA_STATE_WRITE; PLAYER_METADATA_STATE_WRITE;
...@@ -129,12 +127,6 @@ void initPlayerData() { ...@@ -129,12 +127,6 @@ void initPlayerData() {
playerData_pd->decoderControl.seek = 0; playerData_pd->decoderControl.seek = 0;
playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR; playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR;
memset(playerData_pd->decoderControl.utf8url, 0, MAXPATHLEN+1); memset(playerData_pd->decoderControl.utf8url, 0, MAXPATHLEN+1);
memset(playerData_pd->decoderControl.metadata, 0,
DECODE_METADATA_LENGTH);
playerData_pd->decoderControl.title = -1;
playerData_pd->decoderControl.artist = -1;
playerData_pd->decoderControl.album = -1;
playerData_pd->decoderControl.metadataSet = 0;
} }
PlayerData * getPlayerData() { PlayerData * getPlayerData() {
...@@ -144,4 +136,3 @@ PlayerData * getPlayerData() { ...@@ -144,4 +136,3 @@ PlayerData * getPlayerData() {
void freePlayerData() { void freePlayerData() {
shmdt(playerData_pd); shmdt(playerData_pd);
} }
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "../config.h" #include "../config.h"
#include "song.h" #include "song.h"
#include "mpd_types.h"
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> #include <sys/param.h>
...@@ -49,12 +50,18 @@ int showPlaylist(FILE * fp); ...@@ -49,12 +50,18 @@ int showPlaylist(FILE * fp);
int deleteFromPlaylist(FILE * fp, int song); int deleteFromPlaylist(FILE * fp, int song);
int deleteFromPlaylistById(FILE * fp, int song);
int playlistInfo(FILE * fp, int song); int playlistInfo(FILE * fp, int song);
int playlistId(FILE * fp, int song);
int stopPlaylist(FILE * fp); int stopPlaylist(FILE * fp);
int playPlaylist(FILE * fp, int song, int stopOnError); int playPlaylist(FILE * fp, int song, int stopOnError);
int playPlaylistById(FILE * fp, int song, int stopOnError);
int nextSongInPlaylist(FILE * fp); int nextSongInPlaylist(FILE * fp);
void syncPlayerAndPlaylist(); void syncPlayerAndPlaylist();
...@@ -67,12 +74,18 @@ int savePlaylist(FILE * fp, char * utf8file); ...@@ -67,12 +74,18 @@ int savePlaylist(FILE * fp, char * utf8file);
int deletePlaylist(FILE * fp, char * utf8file); int deletePlaylist(FILE * fp, char * utf8file);
int deletePlaylistById(FILE * fp, char * utf8file);
void deleteASongFromPlaylist(Song * song); void deleteASongFromPlaylist(Song * song);
int moveSongInPlaylist(FILE * fp, int from, int to); int moveSongInPlaylist(FILE * fp, int from, int to);
int moveSongInPlaylistById(FILE * fp, int id, int to);
int swapSongsInPlaylist(FILE * fp, int song1, int song2); int swapSongsInPlaylist(FILE * fp, int song1, int song2);
int swapSongsInPlaylistById(FILE * fp, int id1, int id2);
int loadPlaylist(FILE * fp, char * utf8file); int loadPlaylist(FILE * fp, char * utf8file);
int getPlaylistRepeatStatus(); int getPlaylistRepeatStatus();
...@@ -85,6 +98,8 @@ int setPlaylistRandomStatus(FILE * fp, int status); ...@@ -85,6 +98,8 @@ int setPlaylistRandomStatus(FILE * fp, int status);
int getPlaylistCurrentSong(); int getPlaylistCurrentSong();
int getPlaylistSongId(int song);
int getPlaylistLength(); int getPlaylistLength();
unsigned long getPlaylistVersion(); unsigned long getPlaylistVersion();
...@@ -93,7 +108,11 @@ void playPlaylistIfPlayerStopped(); ...@@ -93,7 +108,11 @@ void playPlaylistIfPlayerStopped();
int seekSongInPlaylist(FILE * fp, int song, float time); int seekSongInPlaylist(FILE * fp, int song, float time);
void incrPlaylistVersion(); int seekSongInPlaylistById(FILE * fp, int id, float time);
void playlistVersionChange();
int playlistChanges(FILE * fp, mpd_uint32 version);
#endif #endif
/* vim:set shiftwidth=4 tabstop=8 expandtab: */ /* vim:set shiftwidth=4 tabstop=8 expandtab: */
/* the Music Player Daemon (MPD) /* the Music Player Daemon (MPD)
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
* (c) 2004 Nick Welch (mack@incise.org)
* This project's homepage is: http://www.musicpd.org * This project's homepage is: http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -43,7 +44,7 @@ int handlePendingSignals() { ...@@ -43,7 +44,7 @@ int handlePendingSignals() {
signal_clear(SIGHUP); signal_clear(SIGHUP);
if(!isUpdatingDB()) { if(!isUpdatingDB()) {
readDirectoryDB(); readDirectoryDB();
incrPlaylistVersion(); playlistVersionChange();
} }
if(myfprintfCloseAndOpenLogFile()<0) return COMMAND_RETURN_KILL; if(myfprintfCloseAndOpenLogFile()<0) return COMMAND_RETURN_KILL;
playerCycleLogFiles(); playerCycleLogFiles();
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define SONG_ALBUM "Album: " #define SONG_ALBUM "Album: "
#define SONG_TRACK "Track: " #define SONG_TRACK "Track: "
#define SONG_TITLE "Title: " #define SONG_TITLE "Title: "
#define SONG_NAME "Name: "
#define SONG_TIME "Time: " #define SONG_TIME "Time: "
#define SONG_MTIME "mtime: " #define SONG_MTIME "mtime: "
...@@ -235,6 +236,10 @@ void readSongInfoIntoList(FILE * fp, SongList * list) { ...@@ -235,6 +236,10 @@ void readSongInfoIntoList(FILE * fp, SongList * list) {
if(!song->tag) song->tag = newMpdTag(); if(!song->tag) song->tag = newMpdTag();
song->tag->title = strdup(&(buffer[strlen(SONG_TITLE)])); song->tag->title = strdup(&(buffer[strlen(SONG_TITLE)]));
} }
else if(0==strncmp(SONG_NAME,buffer,strlen(SONG_NAME))) {
if(!song->tag) song->tag = newMpdTag();
song->tag->name = strdup(&(buffer[strlen(SONG_NAME)]));
}
else if(0==strncmp(SONG_TIME,buffer,strlen(SONG_TIME))) { else if(0==strncmp(SONG_TIME,buffer,strlen(SONG_TIME))) {
if(!song->tag) song->tag = newMpdTag(); if(!song->tag) song->tag = newMpdTag();
song->tag->time = atoi(&(buffer[strlen(SONG_TIME)])); song->tag->time = atoi(&(buffer[strlen(SONG_TIME)]));
......
...@@ -43,6 +43,7 @@ void printMpdTag(FILE * fp, MpdTag * tag) { ...@@ -43,6 +43,7 @@ void printMpdTag(FILE * fp, MpdTag * tag) {
if(tag->album) myfprintf(fp,"Album: %s\n",tag->album); if(tag->album) myfprintf(fp,"Album: %s\n",tag->album);
if(tag->track) myfprintf(fp,"Track: %s\n",tag->track); if(tag->track) myfprintf(fp,"Track: %s\n",tag->track);
if(tag->title) myfprintf(fp,"Title: %s\n",tag->title); if(tag->title) myfprintf(fp,"Title: %s\n",tag->title);
if(tag->name) myfprintf(fp,"Name: %s\n",tag->name);
if(tag->time>=0) myfprintf(fp,"Time: %i\n",tag->time); if(tag->time>=0) myfprintf(fp,"Time: %i\n",tag->time);
} }
...@@ -62,6 +63,7 @@ void validateUtf8Tag(MpdTag * tag) { ...@@ -62,6 +63,7 @@ void validateUtf8Tag(MpdTag * tag) {
fixUtf8(tag->album); fixUtf8(tag->album);
fixUtf8(tag->track); fixUtf8(tag->track);
fixUtf8(tag->title); fixUtf8(tag->title);
fixUtf8(tag->name);
} }
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
...@@ -158,6 +160,7 @@ MpdTag * newMpdTag() { ...@@ -158,6 +160,7 @@ MpdTag * newMpdTag() {
ret->artist = NULL; ret->artist = NULL;
ret->title = NULL; ret->title = NULL;
ret->track = NULL; ret->track = NULL;
ret->name = NULL;
ret->time = -1; ret->time = -1;
return ret; return ret;
} }
...@@ -166,6 +169,7 @@ void clearMpdTag(MpdTag * tag) { ...@@ -166,6 +169,7 @@ void clearMpdTag(MpdTag * tag) {
if(tag->artist) free(tag->artist); if(tag->artist) free(tag->artist);
if(tag->album) free(tag->album); if(tag->album) free(tag->album);
if(tag->title) free(tag->title); if(tag->title) free(tag->title);
if(tag->name) free(tag->name);
if(tag->track) free(tag->track); if(tag->track) free(tag->track);
} }
...@@ -183,6 +187,7 @@ MpdTag * mpdTagDup(MpdTag * tag) { ...@@ -183,6 +187,7 @@ MpdTag * mpdTagDup(MpdTag * tag) {
if(tag->album) ret->album = strdup(tag->album); if(tag->album) ret->album = strdup(tag->album);
if(tag->title) ret->title = strdup(tag->title); if(tag->title) ret->title = strdup(tag->title);
if(tag->track) ret->track = strdup(tag->track); if(tag->track) ret->track = strdup(tag->track);
if(tag->name) ret->name = strdup(tag->name);
ret->time = tag->time; ret->time = tag->time;
} }
...@@ -200,7 +205,7 @@ int mpdTagStringsAreEqual(char * s1, char * s2) { ...@@ -200,7 +205,7 @@ int mpdTagStringsAreEqual(char * s1, char * s2) {
int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) { int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) {
if(tag1 == NULL && tag2 == NULL) return 1; if(tag1 == NULL && tag2 == NULL) return 1;
else if(!tag1 || ! !tag2) return 0; else if(!tag1 || !tag2) return 0;
if(tag1->time != tag2->time) return 0; if(tag1->time != tag2->time) return 0;
...@@ -208,6 +213,7 @@ int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) { ...@@ -208,6 +213,7 @@ int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) {
if(!mpdTagStringsAreEqual(tag1->album, tag2->album)) return 0; if(!mpdTagStringsAreEqual(tag1->album, tag2->album)) return 0;
if(!mpdTagStringsAreEqual(tag1->track, tag2->track)) return 0; if(!mpdTagStringsAreEqual(tag1->track, tag2->track)) return 0;
if(!mpdTagStringsAreEqual(tag1->title, tag2->title)) return 0; if(!mpdTagStringsAreEqual(tag1->title, tag2->title)) return 0;
if(!mpdTagStringsAreEqual(tag1->name, tag2->name)) return 0;
return 1; return 1;
} }
...@@ -35,6 +35,7 @@ typedef struct _MpdTag { ...@@ -35,6 +35,7 @@ typedef struct _MpdTag {
char * album; char * album;
char * track; char * track;
char * title; char * title;
char * name;
int time; int time;
} MpdTag; } MpdTag;
...@@ -59,4 +60,3 @@ void validateUtf8Tag(MpdTag * tag); ...@@ -59,4 +60,3 @@ void validateUtf8Tag(MpdTag * tag);
int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2); int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2);
#endif #endif
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment