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.
...@@ -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)
......
...@@ -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
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <unistd.h> #include <unistd.h>
#define COMMAND_PLAY "play" #define COMMAND_PLAY "play"
#define COMMAND_PLAYID "playid"
#define COMMAND_STOP "stop" #define COMMAND_STOP "stop"
#define COMMAND_PAUSE "pause" #define COMMAND_PAUSE "pause"
#define COMMAND_STATUS "status" #define COMMAND_STATUS "status"
...@@ -45,6 +46,7 @@ ...@@ -45,6 +46,7 @@
#define COMMAND_CLOSE "close" #define COMMAND_CLOSE "close"
#define COMMAND_ADD "add" #define COMMAND_ADD "add"
#define COMMAND_DELETE "delete" #define COMMAND_DELETE "delete"
#define COMMAND_DELETEID "deleteid"
#define COMMAND_PLAYLIST "playlist" #define COMMAND_PLAYLIST "playlist"
#define COMMAND_SHUFFLE "shuffle" #define COMMAND_SHUFFLE "shuffle"
#define COMMAND_CLEAR "clear" #define COMMAND_CLEAR "clear"
...@@ -53,6 +55,7 @@ ...@@ -53,6 +55,7 @@
#define COMMAND_LSINFO "lsinfo" #define COMMAND_LSINFO "lsinfo"
#define COMMAND_RM "rm" #define COMMAND_RM "rm"
#define COMMAND_PLAYLISTINFO "playlistinfo" #define COMMAND_PLAYLISTINFO "playlistinfo"
#define COMMAND_PLAYLISTID "playlistid"
#define COMMAND_FIND "find" #define COMMAND_FIND "find"
#define COMMAND_SEARCH "search" #define COMMAND_SEARCH "search"
#define COMMAND_UPDATE "update" #define COMMAND_UPDATE "update"
...@@ -66,14 +69,19 @@ ...@@ -66,14 +69,19 @@
#define COMMAND_CLEAR_ERROR "clearerror" #define COMMAND_CLEAR_ERROR "clearerror"
#define COMMAND_LIST "list" #define COMMAND_LIST "list"
#define COMMAND_MOVE "move" #define COMMAND_MOVE "move"
#define COMMAND_MOVEID "moveid"
#define COMMAND_SWAP "swap" #define COMMAND_SWAP "swap"
#define COMMAND_SWAPID "swapid"
#define COMMAND_SEEK "seek" #define COMMAND_SEEK "seek"
#define COMMAND_SEEKID "seekid"
#define COMMAND_LISTALLINFO "listallinfo" #define COMMAND_LISTALLINFO "listallinfo"
#define COMMAND_PING "ping" #define COMMAND_PING "ping"
#define COMMAND_SETVOL "setvol" #define COMMAND_SETVOL "setvol"
#define COMMAND_PASSWORD "password" #define COMMAND_PASSWORD "password"
#define COMMAND_CROSSFADE "crossfade" #define COMMAND_CROSSFADE "crossfade"
#define COMMAND_URL_HANDLERS "urlhandlers" #define COMMAND_URL_HANDLERS "urlhandlers"
#define COMMAND_PLCHANGES "plchanges"
#define COMMAND_CURRENT "current"
#define COMMAND_STATUS_VOLUME "volume" #define COMMAND_STATUS_VOLUME "volume"
#define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_STATE "state"
...@@ -82,6 +90,7 @@ ...@@ -82,6 +90,7 @@
#define COMMAND_STATUS_PLAYLIST "playlist" #define COMMAND_STATUS_PLAYLIST "playlist"
#define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength" #define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength"
#define COMMAND_STATUS_SONG "song" #define COMMAND_STATUS_SONG "song"
#define COMMAND_STATUS_SONGID "songid"
#define COMMAND_STATUS_TIME "time" #define COMMAND_STATUS_TIME "time"
#define COMMAND_STATUS_BITRATE "bitrate" #define COMMAND_STATUS_BITRATE "bitrate"
#define COMMAND_STATUS_ERROR "error" #define COMMAND_STATUS_ERROR "error"
...@@ -162,12 +171,40 @@ int handlePlay(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -162,12 +171,40 @@ int handlePlay(FILE * fp, unsigned int * permission, int argArrayLength,
return playPlaylist(fp,song,0); return playPlaylist(fp,song,0);
} }
int handlePlayId(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray)
{
int id = -1;
char * test;
if(argArrayLength==2) {
id = strtol(argArray[1],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"need a positive integer");
return -1;
}
}
return playPlaylist(fp, id, 0);
}
int handleStop(FILE * fp, unsigned int * permission, int argArrayLength, int handleStop(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray) char ** argArray)
{ {
return stopPlaylist(fp); return stopPlaylist(fp);
} }
int handleCurrent(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray)
{
int song = getPlaylistCurrentSong();
if(song >= 0) {
return playlistInfo(fp, song);
}
else return 0;
}
int handlePause(FILE * fp, unsigned int * permission, int handlePause(FILE * fp, unsigned int * permission,
int argArrayLength, char ** argArray) int argArrayLength, char ** argArray)
{ {
...@@ -190,6 +227,7 @@ int commandStatus(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -190,6 +227,7 @@ int commandStatus(FILE * fp, unsigned int * permission, int argArrayLength,
int updateJobId; int updateJobId;
int song; int song;
/*syncPlayerAndPlaylist();*/
playPlaylistIfPlayerStopped(); playPlaylistIfPlayerStopped();
switch(getPlayerState()) { switch(getPlayerState()) {
case PLAYER_STATE_STOP: case PLAYER_STATE_STOP:
...@@ -214,7 +252,11 @@ int commandStatus(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -214,7 +252,11 @@ int commandStatus(FILE * fp, unsigned int * permission, int argArrayLength,
myfprintf(fp,"%s: %s\n",COMMAND_STATUS_STATE,state); myfprintf(fp,"%s: %s\n",COMMAND_STATUS_STATE,state);
song = getPlaylistCurrentSong(); song = getPlaylistCurrentSong();
if(song >= 0) myfprintf(fp,"%s: %i\n",COMMAND_STATUS_SONG,song); if(song >= 0) {
myfprintf(fp,"%s: %i\n", COMMAND_STATUS_SONG, song);
myfprintf(fp,"%s: %i\n", COMMAND_STATUS_SONGID,
getPlaylistSongId(song));
}
if(getPlayerState()!=PLAYER_STATE_STOP) { if(getPlayerState()!=PLAYER_STATE_STOP) {
myfprintf(fp,"%s: %i:%i\n",COMMAND_STATUS_TIME,getPlayerElapsedTime(),getPlayerTotalTime()); myfprintf(fp,"%s: %i:%i\n",COMMAND_STATUS_TIME,getPlayerElapsedTime(),getPlayerTotalTime());
myfprintf(fp,"%s: %li\n",COMMAND_STATUS_BITRATE,getPlayerBitRate(),getPlayerTotalTime()); myfprintf(fp,"%s: %li\n",COMMAND_STATUS_BITRATE,getPlayerBitRate(),getPlayerTotalTime());
...@@ -273,6 +315,21 @@ int handleDelete(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -273,6 +315,21 @@ int handleDelete(FILE * fp, unsigned int * permission, int argArrayLength,
return deleteFromPlaylist(fp,song); return deleteFromPlaylist(fp,song);
} }
int handleDeleteId(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray)
{
int id;
char * test;
id = strtol(argArray[1],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"need a positive integer");
return -1;
}
return deleteFromPlaylist(fp, id);
}
int handlePlaylist(FILE * fp, unsigned int * permission, int argArrayLength, int handlePlaylist(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray) char ** argArray)
{ {
...@@ -322,6 +379,20 @@ int handleRm(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -322,6 +379,20 @@ int handleRm(FILE * fp, unsigned int * permission, int argArrayLength,
return deletePlaylist(fp,argArray[1]); return deletePlaylist(fp,argArray[1]);
} }
int handlePlaylistChanges(FILE * fp, unsigned int * permission,
int argArrayLength, char ** argArray)
{
unsigned long version;
char * test;
version = strtoul(argArray[1], &test, 10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG, "need a positive integer");
return -1;
}
return playlistChanges(fp, version);
}
int handlePlaylistInfo(FILE * fp, unsigned int * permission, int handlePlaylistInfo(FILE * fp, unsigned int * permission,
int argArrayLength, char ** argArray) int argArrayLength, char ** argArray)
{ {
...@@ -339,6 +410,23 @@ int handlePlaylistInfo(FILE * fp, unsigned int * permission, ...@@ -339,6 +410,23 @@ int handlePlaylistInfo(FILE * fp, unsigned int * permission,
return playlistInfo(fp,song); return playlistInfo(fp,song);
} }
int handlePlaylistId(FILE * fp, unsigned int * permission,
int argArrayLength, char ** argArray)
{
int id = -1;
char * test;
if(argArrayLength == 2) {
id = strtol(argArray[1],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"%s need a positive integer");
return -1;
}
}
return playlistId(fp, id);
}
int handleFind(FILE * fp, unsigned int * permission, int argArrayLength, int handleFind(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray) char ** argArray)
{ {
...@@ -513,6 +601,28 @@ int handleMove(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -513,6 +601,28 @@ int handleMove(FILE * fp, unsigned int * permission, int argArrayLength,
return moveSongInPlaylist(fp,from,to); return moveSongInPlaylist(fp,from,to);
} }
int handleMoveId(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray)
{
int id;
int to;
char * test;
id = strtol(argArray[1],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"\"%s\" is not a integer", argArray[1]);
return -1;
}
to = strtol(argArray[2],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"\"%s\" is not a integer", argArray[2]);
return -1;
}
return moveSongInPlaylistById(fp, id, to);
}
int handleSwap(FILE * fp, unsigned int * permission, int argArrayLength, int handleSwap(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray) char ** argArray)
{ {
...@@ -535,6 +645,28 @@ int handleSwap(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -535,6 +645,28 @@ int handleSwap(FILE * fp, unsigned int * permission, int argArrayLength,
return swapSongsInPlaylist(fp,song1,song2); return swapSongsInPlaylist(fp,song1,song2);
} }
int handleSwapId(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray)
{
int id1;
int id2;
char * test;
id1 = strtol(argArray[1],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"\"%s\" is not a integer", argArray[1]);
return -1;
}
id2 = strtol(argArray[2],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG, "\"%s\" is not a integer",
argArray[2]);
return -1;
}
return swapSongsInPlaylist(fp, id1, id2);
}
int handleSeek(FILE * fp, unsigned int * permission, int argArrayLength, int handleSeek(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray) char ** argArray)
{ {
...@@ -557,6 +689,28 @@ int handleSeek(FILE * fp, unsigned int * permission, int argArrayLength, ...@@ -557,6 +689,28 @@ int handleSeek(FILE * fp, unsigned int * permission, int argArrayLength,
return seekSongInPlaylist(fp,song,time); return seekSongInPlaylist(fp,song,time);
} }
int handleSeekId(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray)
{
int id;
int time;
char * test;
id = strtol(argArray[1],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"\"%s\" is not a integer", argArray[1]);
return -1;
}
time = strtol(argArray[2],&test,10);
if(*test!='\0') {
commandError(fp, ACK_ERROR_ARG,
"\"%s\" is not a integer", argArray[2]);
return -1;
}
return seekSongInPlaylist(fp, id, time);
}
int handleListAllInfo(FILE * fp, unsigned int * permission, int argArrayLength, int handleListAllInfo(FILE * fp, unsigned int * permission, int argArrayLength,
char ** argArray) char ** argArray)
{ {
...@@ -605,14 +759,18 @@ void initCommands() { ...@@ -605,14 +759,18 @@ void initCommands() {
commandList = makeList(free); commandList = makeList(free);
addCommand(COMMAND_PLAY ,PERMISSION_CONTROL, 0, 1,handlePlay,NULL); addCommand(COMMAND_PLAY ,PERMISSION_CONTROL, 0, 1,handlePlay,NULL);
addCommand(COMMAND_PLAYID ,PERMISSION_CONTROL, 0, 1,handlePlayId,NULL);
addCommand(COMMAND_STOP ,PERMISSION_CONTROL, 0, 0,handleStop,NULL); addCommand(COMMAND_STOP ,PERMISSION_CONTROL, 0, 0,handleStop,NULL);
addCommand(COMMAND_CURRENT ,PERMISSION_READ , 0, 0,handleCurrent,NULL);
addCommand(COMMAND_PAUSE ,PERMISSION_CONTROL, 0, 1,handlePause,NULL); addCommand(COMMAND_PAUSE ,PERMISSION_CONTROL, 0, 1,handlePause,NULL);
addCommand(COMMAND_STATUS ,PERMISSION_READ, 0, 0,commandStatus,NULL); addCommand(COMMAND_STATUS ,PERMISSION_READ, 0, 0,commandStatus,NULL);
addCommand(COMMAND_KILL ,PERMISSION_ADMIN, -1,-1,handleKill,NULL); addCommand(COMMAND_KILL ,PERMISSION_ADMIN, -1,-1,handleKill,NULL);
addCommand(COMMAND_CLOSE ,0, -1,-1,handleClose,NULL); addCommand(COMMAND_CLOSE ,0, -1,-1,handleClose,NULL);
addCommand(COMMAND_ADD ,PERMISSION_ADD, 0, 1,handleAdd,NULL); addCommand(COMMAND_ADD ,PERMISSION_ADD, 0, 1,handleAdd,NULL);
addCommand(COMMAND_DELETE ,PERMISSION_CONTROL, 1, 1,handleDelete,NULL); addCommand(COMMAND_DELETE ,PERMISSION_CONTROL, 1, 1,handleDelete,NULL);
addCommand(COMMAND_DELETEID ,PERMISSION_CONTROL, 1, 1,handleDeleteId,NULL);
addCommand(COMMAND_PLAYLIST ,PERMISSION_READ, 0, 0,handlePlaylist,NULL); addCommand(COMMAND_PLAYLIST ,PERMISSION_READ, 0, 0,handlePlaylist,NULL);
addCommand(COMMAND_PLAYLISTID ,PERMISSION_READ, 0, 0,handlePlaylistId,NULL);
addCommand(COMMAND_SHUFFLE ,PERMISSION_CONTROL, 0, 0,handleShuffle,NULL); addCommand(COMMAND_SHUFFLE ,PERMISSION_CONTROL, 0, 0,handleShuffle,NULL);
addCommand(COMMAND_CLEAR ,PERMISSION_CONTROL, 0, 0,handleClear,NULL); addCommand(COMMAND_CLEAR ,PERMISSION_CONTROL, 0, 0,handleClear,NULL);
addCommand(COMMAND_SAVE ,PERMISSION_CONTROL, 1, 1,handleSave,NULL); addCommand(COMMAND_SAVE ,PERMISSION_CONTROL, 1, 1,handleSave,NULL);
...@@ -633,14 +791,18 @@ void initCommands() { ...@@ -633,14 +791,18 @@ void initCommands() {
addCommand(COMMAND_CLEAR_ERROR ,PERMISSION_CONTROL, 0, 0,handleClearError,NULL); addCommand(COMMAND_CLEAR_ERROR ,PERMISSION_CONTROL, 0, 0,handleClearError,NULL);
addCommand(COMMAND_LIST ,PERMISSION_READ, 1, 2,handleList,NULL); addCommand(COMMAND_LIST ,PERMISSION_READ, 1, 2,handleList,NULL);
addCommand(COMMAND_MOVE ,PERMISSION_CONTROL, 2, 2,handleMove,NULL); addCommand(COMMAND_MOVE ,PERMISSION_CONTROL, 2, 2,handleMove,NULL);
addCommand(COMMAND_MOVEID ,PERMISSION_CONTROL, 2, 2,handleMoveId,NULL);
addCommand(COMMAND_SWAP ,PERMISSION_CONTROL, 2, 2,handleSwap,NULL); addCommand(COMMAND_SWAP ,PERMISSION_CONTROL, 2, 2,handleSwap,NULL);
addCommand(COMMAND_SWAPID ,PERMISSION_CONTROL, 2, 2,handleSwapId,NULL);
addCommand(COMMAND_SEEK ,PERMISSION_CONTROL, 2, 2,handleSeek,NULL); addCommand(COMMAND_SEEK ,PERMISSION_CONTROL, 2, 2,handleSeek,NULL);
addCommand(COMMAND_SEEKID ,PERMISSION_CONTROL, 2, 2,handleSeekId,NULL);
addCommand(COMMAND_LISTALLINFO ,PERMISSION_READ, 0, 1,handleListAllInfo,NULL); addCommand(COMMAND_LISTALLINFO ,PERMISSION_READ, 0, 1,handleListAllInfo,NULL);
addCommand(COMMAND_PING ,0, 0, 0,handlePing,NULL); addCommand(COMMAND_PING ,0, 0, 0,handlePing,NULL);
addCommand(COMMAND_SETVOL ,PERMISSION_CONTROL, 1, 1,handleSetVol,NULL); addCommand(COMMAND_SETVOL ,PERMISSION_CONTROL, 1, 1,handleSetVol,NULL);
addCommand(COMMAND_PASSWORD ,0, 1, 1,handlePassword,NULL); addCommand(COMMAND_PASSWORD ,0, 1, 1,handlePassword,NULL);
addCommand(COMMAND_CROSSFADE ,PERMISSION_CONTROL, 1, 1,handleCrossfade,NULL); addCommand(COMMAND_CROSSFADE ,PERMISSION_CONTROL, 1, 1,handleCrossfade,NULL);
addCommand(COMMAND_URL_HANDLERS,PERMISSION_READ, 0, 0,handleUrlHandlers,NULL); addCommand(COMMAND_URL_HANDLERS,PERMISSION_READ, 0, 0,handleUrlHandlers,NULL);
addCommand(COMMAND_PLCHANGES ,PERMISSION_READ, 1, 1,handlePlaylistChanges,NULL);
sortList(commandList); sortList(commandList);
} }
...@@ -770,7 +932,7 @@ int processCommandInternal(FILE * fp, unsigned int * permission, ...@@ -770,7 +932,7 @@ int processCommandInternal(FILE * fp, unsigned int * permission,
} }
int proccessListOfCommands(FILE * fp, int * permission, int * expired, int proccessListOfCommands(FILE * fp, int * permission, int * expired,
List * list) int listOK, List * list)
{ {
ListNode * node = list->firstNode; ListNode * node = list->firstNode;
ListNode * tempNode; ListNode * tempNode;
...@@ -788,6 +950,7 @@ int proccessListOfCommands(FILE * fp, int * permission, int * expired, ...@@ -788,6 +950,7 @@ int proccessListOfCommands(FILE * fp, int * permission, int * expired,
deleteNodeFromList(list,node); deleteNodeFromList(list,node);
node = tempNode; node = tempNode;
if(ret!=0 || (*expired)!=0) node = NULL; if(ret!=0 || (*expired)!=0) node = NULL;
else if(listOK) myfprintf(fp, "list_OK\n");
command_listNum++; command_listNum++;
} }
......
...@@ -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;
} }
} }
......
...@@ -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:
case HTTP_CONN_STATE_CLOSED: if(data->prebuffer || data->buflen < data->icyMetaint) return 0;
break; break;
case HTTP_CONN_STATE_CLOSED:
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,17 +284,18 @@ int interfaceReadInput(Interface * interface) { ...@@ -281,17 +284,18 @@ 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; ret = 1;
} }
else { else if(strcmp(interface->buffer,
if(strcmp(interface->buffer, INTERFACE_LIST_OK_MODE_BEGIN)
INTERFACE_LIST_MODE_END)
==0) ==0)
{ {
commandError(interface->fp, interface->commandList = makeList(free);
ACK_ERROR_NOT_LIST, interface->commandListSize =
"not in command list mode"); sizeof(List);
ret = -1; interface->commandListOK = 1;
ret = 1;
} }
else { else {
DEBUG("interface %i: process command \"%s\"\n",interface->num,interface->buffer); DEBUG("interface %i: process command \"%s\"\n",interface->num,interface->buffer);
...@@ -301,7 +305,6 @@ int interfaceReadInput(Interface * interface) { ...@@ -301,7 +305,6 @@ int interfaceReadInput(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);
ret = song;
resetPlayerMetadata(); resetPlayerMetadata();
return song;
} }
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: */
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#define BITS_FOR_VERSION 31
#define PLAYLIST_COMMENT '#' #define PLAYLIST_COMMENT '#'
#define PLAYLIST_STATE_STOP 0 #define PLAYLIST_STATE_STOP 0
...@@ -60,15 +58,21 @@ ...@@ -60,15 +58,21 @@
#define PLAYLIST_BUFFER_SIZE 2*MAXPATHLEN #define PLAYLIST_BUFFER_SIZE 2*MAXPATHLEN
#define PLAYLIST_HASH_MULT 4
typedef struct _Playlist { typedef struct _Playlist {
Song ** songs; Song ** songs;
/* holds version a song was modified on */
mpd_uint32 * songMod;
int * order; int * order;
int * numToId;
int * idToNum;
int length; int length;
int current; int current;
int queued; int queued;
int repeat; int repeat;
int random; int random;
unsigned long version; mpd_uint32 version;
} Playlist; } Playlist;
static Playlist playlist; static Playlist playlist;
...@@ -87,10 +91,28 @@ static void swapOrder(int a, int b); ...@@ -87,10 +91,28 @@ static void swapOrder(int a, int b);
static int playPlaylistOrderNumber(FILE * fp, int orderNum); static int playPlaylistOrderNumber(FILE * fp, int orderNum);
static void randomizeOrder(int start, int end); static void randomizeOrder(int start, int end);
void incrPlaylistVersion() { static void incrPlaylistVersion() {
static unsigned long max = ((unsigned long)1<<BITS_FOR_VERSION)-1; static unsigned long max = ((mpd_uint32)1<<31)-1;
playlist.version++; playlist.version++;
if(playlist.version>=max) playlist.version = 0; if(playlist.version>=max) {
int i;
for(i=0; i<playlist.length; i++) {
playlist.songMod[i] = 0;
}
playlist.version = 1;
}
}
void playlistVersionChange() {
int i = 0;
for(i=0; i<playlist.length; i++) {
playlist.songMod[i] = playlist.version;
}
incrPlaylistVersion();
} }
static void incrPlaylistCurrent() { static void incrPlaylistCurrent() {
...@@ -105,10 +127,11 @@ static void incrPlaylistCurrent() { ...@@ -105,10 +127,11 @@ static void incrPlaylistCurrent() {
void initPlaylist() { void initPlaylist() {
char * test; char * test;
int i;
playlist.length = 0; playlist.length = 0;
playlist.repeat = 0; playlist.repeat = 0;
playlist.version = 0; playlist.version = 1;
playlist.random = 0; playlist.random = 0;
playlist.queued = -1; playlist.queued = -1;
playlist.current = -1; playlist.current = -1;
...@@ -136,7 +159,11 @@ void initPlaylist() { ...@@ -136,7 +159,11 @@ void initPlaylist() {
} }
playlist.songs = malloc(sizeof(Song *)*playlist_max_length); playlist.songs = malloc(sizeof(Song *)*playlist_max_length);
playlist.order = malloc(sizeof(Song *)*playlist_max_length); playlist.songMod = malloc(sizeof(mpd_uint32)*playlist_max_length);
playlist.order = malloc(sizeof(int)*playlist_max_length);
playlist.idToNum = malloc(sizeof(int)*playlist_max_length*
PLAYLIST_HASH_MULT);
playlist.numToId = malloc(sizeof(int)*playlist_max_length);
memset(playlist.songs,0,sizeof(char *)*playlist_max_length); memset(playlist.songs,0,sizeof(char *)*playlist_max_length);
...@@ -146,6 +173,22 @@ void initPlaylist() { ...@@ -146,6 +173,22 @@ void initPlaylist() {
playlist_stateFile = getConf()[CONF_STATE_FILE]; playlist_stateFile = getConf()[CONF_STATE_FILE];
} }
for(i=0; i<playlist_max_length*PLAYLIST_HASH_MULT; i++) {
playlist.idToNum[i] = -1;
}
}
static int getNextId() {
static int cur = 0;
while(playlist.idToNum[cur] != -1) {
cur++;
if(cur >= playlist_max_length*PLAYLIST_HASH_MULT) {
cur = 0;
}
}
return cur;
} }
void finishPlaylist() { void finishPlaylist() {
...@@ -155,10 +198,19 @@ void finishPlaylist() { ...@@ -155,10 +198,19 @@ void finishPlaylist() {
freeJustSong(playlist.songs[i]); freeJustSong(playlist.songs[i]);
} }
} }
playlist.length = 0;
free(playlist.songs); free(playlist.songs);
playlist.songs = NULL; playlist.songs = NULL;
free(playlist.songMod);
playlist.songMod = NULL;
free(playlist.order); free(playlist.order);
playlist.order = NULL; playlist.order = NULL;
free(playlist.idToNum);
playlist.idToNum = NULL;
free(playlist.numToId);
playlist.numToId = NULL;
} }
int clearPlaylist(FILE * fp) { int clearPlaylist(FILE * fp) {
...@@ -170,6 +222,7 @@ int clearPlaylist(FILE * fp) { ...@@ -170,6 +222,7 @@ int clearPlaylist(FILE * fp) {
if(playlist.songs[i]->type == SONG_TYPE_URL) { if(playlist.songs[i]->type == SONG_TYPE_URL) {
freeJustSong(playlist.songs[i]); freeJustSong(playlist.songs[i]);
} }
playlist.idToNum[playlist.numToId[i]] = -1;
playlist.songs[i] = NULL; playlist.songs[i] = NULL;
} }
playlist.length = 0; playlist.length = 0;
...@@ -364,8 +417,33 @@ void readPlaylistState() { ...@@ -364,8 +417,33 @@ void readPlaylistState() {
} }
} }
int playlistInfo(FILE * fp,int song) { void printPlaylistSongInfo(FILE * fp, int song) {
MpdTag * tag; MpdTag * tag;
myfprintf(fp, "file: %s\n", (playlist.songs[song])->utf8url);
if((tag = (playlist.songs[song])->tag)) {
printMpdTag(fp, tag);
}
myfprintf(fp, "Num: %i\n", song);
myfprintf(fp, "Id: %i\n", playlist.numToId[song]);
}
int playlistChanges(FILE * fp, mpd_uint32 version) {
int i;
for(i=0; i<playlist.length; i++) {
if(version > playlist.version ||
playlist.songMod[i] >= version ||
playlist.songMod[i] == 0)
{
printPlaylistSongInfo(fp, i);
}
}
return 0;
}
int playlistInfo(FILE * fp, int song) {
int i; int i;
int begin = 0; int begin = 0;
int end = playlist.length; int end = playlist.length;
...@@ -380,22 +458,54 @@ int playlistInfo(FILE * fp,int song) { ...@@ -380,22 +458,54 @@ int playlistInfo(FILE * fp,int song) {
return -1; return -1;
} }
for(i=begin;i<end;i++) { for(i=begin; i<end; i++) printPlaylistSongInfo(fp, i);
myfprintf(fp,"file: %s\n",(playlist.songs[i])->utf8url);
if((tag = (playlist.songs[i])->tag)) { return 0;
printMpdTag(fp,tag); }
}
# define checkSongId(id) { \
if(id < 0 || id >= PLAYLIST_HASH_MULT*playlist_max_length || \
playlist.idToNum[id] == -1 ) \
{ \
commandError(fp, ACK_ERROR_NO_EXIST, \
"song id doesn't exist: \"%i\"", id); \
return -1; \
} \
}
int playlistId(FILE * fp, int id) {
int i;
int begin = 0;
int end = playlist.length;
if(id>=0) {
checkSongId(id);
begin = playlist.idToNum[id];
end = begin+1;
} }
for(i=begin; i<end; i++) printPlaylistSongInfo(fp, i);
return 0; return 0;
} }
void swapSongs(int song1, int song2) { void swapSongs(int song1, int song2) {
Song * temp; Song * sTemp;
int iTemp;
temp = playlist.songs[song1]; sTemp = playlist.songs[song1];
playlist.songs[song1] = playlist.songs[song2]; playlist.songs[song1] = playlist.songs[song2];
playlist.songs[song2] = temp; playlist.songs[song2] = sTemp;
playlist.songMod[song1] = playlist.version;
playlist.songMod[song2] = playlist.version;
playlist.idToNum[playlist.numToId[song1]] = song2;
playlist.idToNum[playlist.numToId[song2]] = song1;
iTemp = playlist.numToId[song1];
playlist.numToId[song1] = playlist.numToId[song2];
playlist.numToId[song2] = iTemp;
} }
void queueNextSongInPlaylist() { void queueNextSongInPlaylist() {
...@@ -488,7 +598,7 @@ int addToPlaylist(FILE * fp, char * url) { ...@@ -488,7 +598,7 @@ int addToPlaylist(FILE * fp, char * url) {
} }
else { else {
commandError(fp, ACK_ERROR_NO_EXIST, commandError(fp, ACK_ERROR_NO_EXIST,
"\"%s\" is not in the music db or is" "\"%s\" is not in the music db or is "
"not a valid url\n", url); "not a valid url\n", url);
return -1; return -1;
} }
...@@ -512,7 +622,10 @@ int addSongToPlaylist(FILE * fp, Song * song) { ...@@ -512,7 +622,10 @@ int addSongToPlaylist(FILE * fp, Song * song) {
} }
playlist.songs[playlist.length] = song; playlist.songs[playlist.length] = song;
playlist.songMod[playlist.length] = playlist.version;
playlist.order[playlist.length] = playlist.length; playlist.order[playlist.length] = playlist.length;
playlist.numToId[playlist.length] = getNextId();
playlist.idToNum[playlist.numToId[playlist.length]] = playlist.length;
playlist.length++; playlist.length++;
if(playlist.random) { if(playlist.random) {
...@@ -548,7 +661,6 @@ int swapSongsInPlaylist(FILE * fp, int song1, int song2) { ...@@ -548,7 +661,6 @@ int swapSongsInPlaylist(FILE * fp, int song1, int song2) {
return -1; return -1;
} }
if(playlist_state==PLAYLIST_STATE_PLAY) { if(playlist_state==PLAYLIST_STATE_PLAY) {
if(playlist.queued>=0) { if(playlist.queued>=0) {
queuedSong = playlist.order[playlist.queued]; queuedSong = playlist.order[playlist.queued];
...@@ -586,6 +698,21 @@ int swapSongsInPlaylist(FILE * fp, int song1, int song2) { ...@@ -586,6 +698,21 @@ int swapSongsInPlaylist(FILE * fp, int song1, int song2) {
return 0; return 0;
} }
int swapSongsInPlaylistById(FILE * fp, int id1, int id2) {
checkSongId(id1);
checkSongId(id2);
return swapSongsInPlaylist(fp, playlist.idToNum[id1],
playlist.idToNum[id2]);
}
#define moveSongFromTo(from, to) { \
playlist.idToNum[playlist.numToId[from]] = to; \
playlist.numToId[to] = playlist.numToId[from]; \
playlist.songs[to] = playlist.songs[from]; \
playlist.songMod[to] = playlist.version; \
}
int deleteFromPlaylist(FILE * fp, int song) { int deleteFromPlaylist(FILE * fp, int song) {
int i; int i;
int songOrder; int songOrder;
...@@ -610,9 +737,11 @@ int deleteFromPlaylist(FILE * fp, int song) { ...@@ -610,9 +737,11 @@ int deleteFromPlaylist(FILE * fp, int song) {
freeJustSong(playlist.songs[song]); freeJustSong(playlist.songs[song]);
} }
playlist.idToNum[playlist.numToId[song]] = -1;
/* delete song from songs array */ /* delete song from songs array */
for(i=song;i<playlist.length-1;i++) { for(i=song;i<playlist.length-1;i++) {
playlist.songs[i] = playlist.songs[i+1]; moveSongFromTo(i+1, i);
} }
/* now find it in the order array */ /* now find it in the order array */
for(i=0;i<playlist.length-1;i++) { for(i=0;i<playlist.length-1;i++) {
...@@ -652,6 +781,12 @@ int deleteFromPlaylist(FILE * fp, int song) { ...@@ -652,6 +781,12 @@ int deleteFromPlaylist(FILE * fp, int song) {
return 0; return 0;
} }
int deleteFromPlaylistById(FILE * fp, int id) {
checkSongId(id);
return deleteFromPlaylist(fp, playlist.idToNum[id]);
}
void deleteASongFromPlaylist(Song * song) { void deleteASongFromPlaylist(Song * song) {
int i; int i;
...@@ -743,15 +878,27 @@ int playPlaylist(FILE * fp, int song, int stopOnError) { ...@@ -743,15 +878,27 @@ int playPlaylist(FILE * fp, int song, int stopOnError) {
return playPlaylistOrderNumber(fp,i); return playPlaylistOrderNumber(fp,i);
} }
int playPlaylistById(FILE * fp, int id, int stopOnError) {
if(id == -1) {
return playPlaylist(fp, id, stopOnError);
}
checkSongId(id);
return playPlaylist(fp, playlist.idToNum[id], stopOnError);
}
void syncCurrentPlayerDecodeMetadata() { void syncCurrentPlayerDecodeMetadata() {
Song * songPlayer = playerCurrentDecodeSong(); Song * songPlayer = playerCurrentDecodeSong();
Song * song; Song * song;
int songNum;
if(!songPlayer) return; if(!songPlayer) return;
if(playlist_state!=PLAYLIST_STATE_PLAY) return; if(playlist_state!=PLAYLIST_STATE_PLAY) return;
song = playlist.songs[playlist.order[playlist.current]]; songNum = playlist.order[playlist.current];
song = playlist.songs[songNum];
if(song->type == SONG_TYPE_URL && if(song->type == SONG_TYPE_URL &&
0 == strcmp(song->utf8url, songPlayer->utf8url) && 0 == strcmp(song->utf8url, songPlayer->utf8url) &&
...@@ -759,6 +906,7 @@ void syncCurrentPlayerDecodeMetadata() { ...@@ -759,6 +906,7 @@ void syncCurrentPlayerDecodeMetadata() {
{ {
if(song->tag) freeMpdTag(song->tag); if(song->tag) freeMpdTag(song->tag);
song->tag = mpdTagDup(songPlayer->tag); song->tag = mpdTagDup(songPlayer->tag);
playlist.songMod[songNum] = playlist.version;
incrPlaylistVersion(); incrPlaylistVersion();
} }
} }
...@@ -859,6 +1007,7 @@ int setPlaylistRepeatStatus(FILE * fp, int status) { ...@@ -859,6 +1007,7 @@ int setPlaylistRepeatStatus(FILE * fp, int status) {
int moveSongInPlaylist(FILE * fp, int from, int to) { int moveSongInPlaylist(FILE * fp, int from, int to) {
int i; int i;
Song * tmpSong; Song * tmpSong;
int tmpId;
int queuedSong = -1; int queuedSong = -1;
int currentSong = -1; int currentSong = -1;
...@@ -890,12 +1039,20 @@ int moveSongInPlaylist(FILE * fp, int from, int to) { ...@@ -890,12 +1039,20 @@ int moveSongInPlaylist(FILE * fp, int from, int to) {
} }
tmpSong = playlist.songs[from]; tmpSong = playlist.songs[from];
tmpId = playlist.numToId[from];
/* move songs to one less in from->to */ /* move songs to one less in from->to */
for(i=from;i<to;i++) playlist.songs[i] = playlist.songs[i+1]; for(i=from;i<to;i++) {
moveSongFromTo(i+1, i);
}
/* move songs to one more in to->from */ /* move songs to one more in to->from */
for(i=from;i>to;i--) playlist.songs[i] = playlist.songs[i-1]; for(i=from;i>to;i--) {
moveSongFromTo(i-1, i);
}
/* put song at _to_ */ /* put song at _to_ */
playlist.idToNum[playlist.numToId[tmpId]] = to;
playlist.numToId[to] = tmpId;
playlist.songs[to] = tmpSong; playlist.songs[to] = tmpSong;
playlist.songMod[to] = playlist.version;
/* now deal with order */ /* now deal with order */
if(playlist.random) { if(playlist.random) {
for(i=0;i<playlist.length;i++) { for(i=0;i<playlist.length;i++) {
...@@ -924,6 +1081,12 @@ int moveSongInPlaylist(FILE * fp, int from, int to) { ...@@ -924,6 +1081,12 @@ int moveSongInPlaylist(FILE * fp, int from, int to) {
return 0; return 0;
} }
int moveSongInPlaylistById(FILE * fp, int id1, int to) {
checkSongId(id1);
return moveSongInPlaylist(fp, playlist.idToNum[id1], to);
}
void orderPlaylist() { void orderPlaylist() {
int i; int i;
...@@ -984,11 +1147,16 @@ int setPlaylistRandomStatus(FILE * fp, int status) { ...@@ -984,11 +1147,16 @@ int setPlaylistRandomStatus(FILE * fp, int status) {
if(status!=statusWas) { if(status!=statusWas) {
if(playlist.random) { if(playlist.random) {
if(playlist_state==PLAYLIST_STATE_PLAY) { /*if(playlist_state==PLAYLIST_STATE_PLAY) {
randomizeOrder(playlist.current+1, randomizeOrder(playlist.current+1,
playlist.length-1); playlist.length-1);
} }
else randomizeOrder(0,playlist.length-1); else */randomizeOrder(0,playlist.length-1);
if(playlist.current >= 0 &&
playlist.current < playlist.length)
{
swapOrder(playlist.current, 0);
}
} }
else orderPlaylist(); else orderPlaylist();
} }
...@@ -1115,8 +1283,8 @@ int savePlaylist(FILE * fp, char * utf8file) { ...@@ -1115,8 +1283,8 @@ int savePlaylist(FILE * fp, char * utf8file) {
free(rfile); free(rfile);
if(0==stat(actualFile,&st)) { if(0==stat(actualFile,&st)) {
myfprintf(fp, "a file or directory already exists with the name" commandError(fp, ACK_ERROR_EXIST, "a file or directory already "
" \"%s\"", utf8file); "exists with the name \"%s\"", utf8file);
return -1; return -1;
} }
...@@ -1285,3 +1453,13 @@ int seekSongInPlaylist(FILE * fp, int song, float time) { ...@@ -1285,3 +1453,13 @@ int seekSongInPlaylist(FILE * fp, int song, float time) {
return playerSeek(fp, playlist.songs[playlist.order[i]], time); return playerSeek(fp, playlist.songs[playlist.order[i]], time);
} }
int seekSongInPlaylistById(FILE * fp, int id, float time) {
checkSongId(id);
return seekSongInPlaylist(fp, playlist.idToNum[id], time);
}
int getPlaylistSongId(int song) {
return playlist.numToId[song];
}
...@@ -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