Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
82ba78e0
Commit
82ba78e0
authored
Nov 10, 2008
by
Led
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
0.6.2
parent
026cefdb
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
538 additions
and
157 deletions
+538
-157
COMMANDS
COMMANDS
+10
-1
Changelog
Changelog
+7
-0
Makefile
Makefile
+1
-1
TODO
TODO
+11
-6
command.c
command.c
+32
-5
conf.c
conf.c
+21
-13
conf.h
conf.h
+2
-0
interface.c
interface.c
+11
-3
main.c
main.c
+6
-6
mpdconf.example
mpdconf.example
+2
-0
mpg123.c
mpg123.c
+13
-4
ogg.c
ogg.c
+2
-102
ogg_decode.c
ogg_decode.c
+290
-0
ogg_decode.h
ogg_decode.h
+35
-0
playlist.c
playlist.c
+33
-3
playlist.h
playlist.h
+2
-0
tables.c
tables.c
+57
-12
tables.h
tables.h
+3
-1
No files found.
COMMANDS
View file @
82ba78e0
...
...
@@ -40,6 +40,9 @@ find <string type> <string what>
kill
kill mpd
listall
lists all available songs (without tag info)
load <string name>
loads the playlist _name_.m3u from the playlist directory
...
...
@@ -51,11 +54,14 @@ ls <string directory>
lsinfo <string directory>
list contents of _directory_, from the db. _directory_ is optional
next
plays next song in playlist
pause
pause/resume playing
play <int song>
be
ing playling playlist at song number _song_
be
gin playling playlist at song number _song_, _song_ is optiional
playlist
displays the current playlist
...
...
@@ -64,6 +70,9 @@ playlist
playlistinfo
displays information about the current playlist
previous
plays previous song in playlist
rm <string name>
removes the playlist <name>.m3u from the playlist directory
...
...
Changelog
View file @
82ba78e0
ver 0.6.2 (2003/6/11)
1) Buffer support for ogg
2) new config file options: "connection_timeout" and "mpg123_ignore_junk"
3) new commands: "next", "previous", and "listall"
4) Search by filename
5) bug fix for pause when playing mp3's
ver 0.6.1 (2003/5/29)
1) Add conf file support
2) Fix a bug when doing mp3stop (do wait3(NULL,WNOHANG|WUNTRACED,NULL))
...
...
Makefile
View file @
82ba78e0
...
...
@@ -16,7 +16,7 @@ DFLAGS = -MM $(INCLUDES) $(HAVE_OGG)
SOURCES
=
main.c buffer2array.c mpg123.c interface.c command.c playlist.c ls.c
\
id3v2lib/charset.c id3v2lib/lib_id3v2.3.c id3v1lib/lib_id3v1.c
\
id3v2lib/lib_id3v2.2.c song.c list.c directory.c tables.c utils.c
\
tag.c player.c ogg.c listen.c conf.c
tag.c player.c ogg.c listen.c conf.c
ogg_decode.c
OBJECTS
=
$
(
SOURCES:.c
=
.o
)
DEPENDFILE
=
Makefile.depend
...
...
TODO
View file @
82ba78e0
1) Search by Filename
2) buffer support for OGG
3) use autoconf and automake
4) broadcast messages (including status changes/updates)
5) store song times (possibly after playing)
6) add a set a flags (such as BAD MP3)
1) make timeout and max connections configurabe via config file
2) volume control
3) use mpglib from mpg123 for mp3 support
4) use autoconf and automake
5) broadcast messages (including status changes/updates)
6) store song times (possibly after playing)
7) add a set a flags (such as BAD MP3)
possibly:
---------
reference songs by an id #
command.c
View file @
82ba78e0
...
...
@@ -47,6 +47,9 @@
#define COMMAND_FIND "find"
#define COMMAND_SEARCH "search"
#define COMMAND_UPDATE "update"
#define COMMAND_NEXT "next"
#define COMMAND_PREVIOUS "previous"
#define COMMAND_LISTALL "listall"
extern
Playlist
playlist
;
...
...
@@ -89,15 +92,18 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
if
(
0
==
strcmp
(
argArray
[
0
],
COMMAND_PLAY
))
{
int
song
;
char
*
test
;
if
(
argArrayLength
!=
2
)
{
if
(
argArrayLength
>
2
)
{
fprintf
(
fp
,
"%s too many arguments for
\"
%s
\"\n
"
,
COMMAND_RESPOND_ERROR
,
argArray
[
0
]);
return
-
1
;
}
song
=
strtol
(
argArray
[
1
],
&
test
,
10
);
if
(
*
test
!=
'\0'
)
{
fprintf
(
fp
,
"%s need a positive integer
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
if
(
argArrayLength
==
2
)
{
song
=
strtol
(
argArray
[
1
],
&
test
,
10
);
if
(
*
test
!=
'\0'
)
{
fprintf
(
fp
,
"%s need a positive integer
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
}
}
else
song
=
0
;
return
playPlaylist
(
fp
,
song
);
}
else
if
(
0
==
strcmp
(
argArray
[
0
],
COMMAND_STOP
))
{
...
...
@@ -273,6 +279,27 @@ int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
}
return
updateMp3Directory
(
fp
);
}
else
if
(
0
==
strcmp
(
argArray
[
0
],
COMMAND_NEXT
))
{
if
(
argArrayLength
!=
1
)
{
fprintf
(
fp
,
"%s wrong number of arguments for
\"
%s
\"\n
"
,
COMMAND_RESPOND_ERROR
,
argArray
[
0
]);
return
-
1
;
}
return
nextSongInPlaylist
(
fp
);
}
else
if
(
0
==
strcmp
(
argArray
[
0
],
COMMAND_PREVIOUS
))
{
if
(
argArrayLength
!=
1
)
{
fprintf
(
fp
,
"%s wrong number of arguments for
\"
%s
\"\n
"
,
COMMAND_RESPOND_ERROR
,
argArray
[
0
]);
return
-
1
;
}
return
previousSongInPlaylist
(
fp
);
}
else
if
(
0
==
strcmp
(
argArray
[
0
],
COMMAND_LISTALL
))
{
if
(
argArrayLength
!=
1
)
{
fprintf
(
fp
,
"%s wrong number of arguments for
\"
%s
\"\n
"
,
COMMAND_RESPOND_ERROR
,
argArray
[
0
]);
return
-
1
;
}
return
printAllSongsInSongTable
(
fp
);
}
else
{
fprintf
(
fp
,
"%s Unknown command
\"
%s
\"\n
"
,
COMMAND_RESPOND_ERROR
,
argArray
[
0
]);
return
-
1
;
...
...
conf.c
View file @
82ba78e0
...
...
@@ -28,11 +28,14 @@
#define MAX_STRING_SIZE MAXPATHLEN+80
#define CONF_NUMBER_OF_PARAMS
7
#define CONF_NUMBER_OF_PARAMS
9
#define CONF_NUMBER_OF_PATHS 4
#define CONF_NUMBER_OF_REQUIRED 5
#define CONF_MPG123_COMMAND_DEFAULT "mpg123 -b 2048 -R foo"
#define CONF_MPG123_PROCESS_DEFAULT "mpg123"
#define CONF_MPG123_IGNORE_JUNK_DEFAULT "yes"
#define CONF_CONNECTION_TIMEOUT_DEFAULT "60"
char
conf_strings
[
CONF_NUMBER_OF_PARAMS
][
24
]
=
{
"mpg123_command"
,
...
...
@@ -41,7 +44,9 @@ char conf_strings[CONF_NUMBER_OF_PARAMS][24] = {
"playlist_directory"
,
"log_file"
,
"error_file"
,
"mpg123_process"
"mpg123_process"
,
"mpg123_ignore_junk"
,
"connection_timeout"
};
int
conf_absolutePaths
[
CONF_NUMBER_OF_PATHS
]
=
{
...
...
@@ -51,6 +56,14 @@ int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = {
CONF_ERROR_FILE
};
int
conf_required
[
CONF_NUMBER_OF_REQUIRED
]
=
{
CONF_MUSIC_DIRECTORY
,
CONF_PLAYLIST_DIRECTORY
,
CONF_LOG_FILE
,
CONF_ERROR_FILE
,
CONF_PORT
};
char
*
conf_params
[
CONF_NUMBER_OF_PARAMS
];
void
initConf
()
{
...
...
@@ -61,6 +74,8 @@ void initConf() {
/* we don't specify these on the command line */
conf_params
[
CONF_MPG123_COMMAND
]
=
strdup
(
CONF_MPG123_COMMAND_DEFAULT
);
conf_params
[
CONF_MPG123_PROCESS
]
=
strdup
(
CONF_MPG123_PROCESS_DEFAULT
);
conf_params
[
CONF_MPG123_IGNORE_JUNK
]
=
strdup
(
CONF_MPG123_IGNORE_JUNK_DEFAULT
);
conf_params
[
CONF_CONNECTION_TIMEOUT
]
=
strdup
(
CONF_CONNECTION_TIMEOUT_DEFAULT
);
}
char
**
readConf
(
char
*
file
)
{
...
...
@@ -69,12 +84,6 @@ char ** readConf(char * file) {
char
**
array
;
int
i
;
/* we don't specify these on the command line */
free
(
conf_params
[
CONF_MPG123_COMMAND
]);
free
(
conf_params
[
CONF_MPG123_PROCESS
]);
conf_params
[
CONF_MPG123_COMMAND
]
=
NULL
;
conf_params
[
CONF_MPG123_PROCESS
]
=
NULL
;
if
(
!
(
fp
=
fopen
(
file
,
"r"
)))
{
fprintf
(
stderr
,
"problems opening file %s for reading
\n
"
,
file
);
exit
(
-
1
);
...
...
@@ -92,8 +101,7 @@ char ** readConf(char * file) {
exit
(
-
1
);
}
if
(
conf_params
[
i
]
!=
NULL
)
{
fprintf
(
stderr
,
"%s has already been assigned
\n
"
,
conf_strings
[
i
]);
exit
(
-
1
);
free
(
conf_params
[
i
]);
}
conf_params
[
i
]
=
strdup
(
array
[
1
]);
free
(
array
[
0
]);
...
...
@@ -103,9 +111,9 @@ char ** readConf(char * file) {
fclose
(
fp
);
for
(
i
=
0
;
i
<
CONF_NUMBER_OF_
PARAMS
;
i
++
)
{
if
(
conf_params
[
i
]
==
NULL
)
{
fprintf
(
stderr
,
"%s is unassinged in conf file
\n
"
,
conf_strings
[
i
]);
for
(
i
=
0
;
i
<
CONF_NUMBER_OF_
REQUIRED
;
i
++
)
{
if
(
conf_params
[
conf_required
[
i
]
]
==
NULL
)
{
fprintf
(
stderr
,
"%s is unassinged in conf file
\n
"
,
conf_strings
[
conf_required
[
i
]
]);
exit
(
-
1
);
}
}
...
...
conf.h
View file @
82ba78e0
...
...
@@ -26,6 +26,8 @@
#define CONF_LOG_FILE 4
#define CONF_ERROR_FILE 5
#define CONF_MPG123_PROCESS 6
#define CONF_MPG123_IGNORE_JUNK 7
#define CONF_CONNECTION_TIMEOUT 8
/* do not free the return value, it is a static variable */
char
**
readConf
(
char
*
file
);
...
...
interface.c
View file @
82ba78e0
...
...
@@ -19,6 +19,7 @@
#include "interface.h"
#include "buffer2array.h"
#include "command.h"
#include "conf.h"
#include <unistd.h>
#include <stdio.h>
...
...
@@ -29,14 +30,14 @@
#include <string.h>
#include <fcntl.h>
#define VERSION "0.6.
1
"
#define VERSION "0.6.
2
"
#define GREETING "MPD"
#define INTERFACE_MAX_BUFFER_LENGTH 1024
#define INTERFACE_MAX_CONNECTIONS 5
#define INTERFACE_TIMEOUT 60
int
interface_timeout
;
typedef
struct
_Interface
{
char
buffer
[
INTERFACE_MAX_BUFFER_LENGTH
+
1
];
...
...
@@ -167,10 +168,17 @@ int readInputFromInterfaces() {
void
initInterfaces
()
{
int
i
;
char
*
test
;
for
(
i
=
0
;
i
<
INTERFACE_MAX_CONNECTIONS
;
i
++
)
{
interfaces
[
i
].
open
=
0
;
}
interface_timeout
=
strtol
((
getConf
())[
CONF_CONNECTION_TIMEOUT
],
&
test
,
10
);
if
(
*
test
!=
'\0'
)
{
fprintf
(
stderr
,
"connection timeout
\"
%s
\"
is not an integer
\n
"
,(
getConf
())[
CONF_CONNECTION_TIMEOUT
]);
exit
(
-
1
);
}
}
void
closeAllInterfaces
()
{
...
...
@@ -197,7 +205,7 @@ void closeOldInterfaces() {
int
i
;
for
(
i
=
0
;
i
<
INTERFACE_MAX_CONNECTIONS
;
i
++
)
{
if
(
interfaces
[
i
].
open
&&
(
time
(
NULL
)
-
interfaces
[
i
].
lastTime
>
INTERFACE_TIMEOUT
))
{
if
(
interfaces
[
i
].
open
&&
(
time
(
NULL
)
-
interfaces
[
i
].
lastTime
>
interface_timeout
))
{
closeInterface
(
&
(
interfaces
[
i
]));
}
}
...
...
main.c
View file @
82ba78e0
...
...
@@ -50,11 +50,6 @@ int main(int argc, char * argv[]) {
char
*
logFile
;
char
*
errorFile
;
if
(
argc
!=
6
&&
argc
!=
2
)
{
usage
(
argv
);
return
-
1
;
}
initConf
();
if
(
argc
==
6
)
{
...
...
@@ -72,6 +67,11 @@ int main(int argc, char * argv[]) {
logFile
=
conf
[
CONF_LOG_FILE
];
errorFile
=
conf
[
CONF_ERROR_FILE
];
}
else
{
usage
(
argv
);
return
-
1
;
}
if
((
port
=
atoi
(
portStr
))
<
0
)
{
fprintf
(
stderr
,
"problem with port number
\n
"
);
...
...
@@ -104,8 +104,8 @@ int main(int argc, char * argv[]) {
getcwd
(
playlistDir
,
MAXPATHLEN
-
strlen
(
playlistDirArg
)
-
1
);
strcat
(
playlistDir
,
"/"
);
strcat
(
playlistDir
,
playlistDirArg
);
strcat
(
playlistDir
,
"/"
);
}
strcat
(
playlistDir
,
"/"
);
if
((
stat
(
playlistDir
,
&
st
))
<
0
)
{
fprintf
(
stderr
,
"problem stat'ing
\"
%s
\"\n
"
,
playlistDirArg
);
return
-
1
;
...
...
mpdconf.example
View file @
82ba78e0
...
...
@@ -5,3 +5,5 @@ log_file "/home/shank/mpd.log"
error_file "/home/shank/mpd.error"
mpg123_command "mpg123 -b 2048 -R foo"
mpg123_process "mpg123"
mpg123_ignore_junk "yes"
connection_timeout "60"
mpg123.c
View file @
82ba78e0
...
...
@@ -53,6 +53,7 @@ int mpg123_leavePlay = 0;
int
mpg123_leavePause
=
0
;
int
mpg123_error
=
0
;
int
mpg123_lastFrame
=
0
;
int
mpg123_done
=
0
;
char
mpg123_currentSong
[
MAXPATHLEN
+
1
]
=
"
\0
"
;
int
mpg123readline
();
...
...
@@ -80,6 +81,7 @@ int mpg123init() {
int
fd_send
[
2
],
fd_recv
[
2
],
fd_stderr
[
2
];
mpg123_error
=
0
;
mpg123_done
=
0
;
mpg123_currentSong
[
0
]
=
'\0'
;
if
(
socketpair
(
AF_UNIX
,
SOCK_STREAM
,
0
,
fd_send
)
<
0
)
{
...
...
@@ -218,8 +220,8 @@ int mpg123stop(FILE * fp) {
fprintf
(
fp
,
"%s problems write'ing
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
}
/* wait upto
1
s to get SIGCHLD */
while
(
i
<
1
0
&&
mpg123_pid
>
0
)
{
/* wait upto
3
s to get SIGCHLD */
while
(
i
<
3
0
&&
mpg123_pid
>
0
)
{
usleep
(
100000
);
/* wait for 10ms for mpg123 to die */
wait3
(
NULL
,
WNOHANG
|
WUNTRACED
,
NULL
);
while
(
mpg123readline
());
...
...
@@ -239,7 +241,9 @@ int mpg123stop(FILE * fp) {
int
mpg123pause
(
FILE
*
fp
)
{
char
string
[
1024
];
if
(
mpg123_pid
>
0
)
{
mpg123processMessages
();
if
(
mpg123_pid
>
0
&&
!
mpg123_done
)
{
sprintf
(
string
,
"PAUSE
\n
"
);
if
(
write
(
mpg123_send
,
string
,
strlen
(
string
))
<
0
)
{
fprintf
(
fp
,
"%s problems write'ing
\n
"
,
COMMAND_RESPOND_ERROR
);
...
...
@@ -309,10 +313,13 @@ int mpg123gotErrors() {
if
(
errorBuffer
[
errorBufferLength
]
==
'\0'
||
errorBuffer
[
errorBufferLength
]
==
'\n'
||
errorBufferLength
==
MAX_BUFFER_LENGTH
)
{
errorBuffer
[
errorBufferLength
]
=
'\0'
;
errorBufferLength
=
0
;
fprintf
(
stderr
,
"%s file:
\"
%s
\"
: %s
\n
"
,
COMMAND_RESPOND_ERROR
,
mpg123_currentSong
,
errorBuffer
);
if
(
0
==
strncmp
(
"Junk at the beginning"
,
errorBuffer
,
strlen
(
"Junk"
)))
{
if
(
0
!=
strcmp
(
"yes"
,(
getConf
())[
CONF_MPG123_IGNORE_JUNK
]))
{
fprintf
(
stderr
,
"%s file:
\"
%s
\"
: %s
\n
"
,
COMMAND_RESPOND_ERROR
,
mpg123_currentSong
,
errorBuffer
);
}
return
0
;
}
fprintf
(
stderr
,
"%s file:
\"
%s
\"
: %s
\n
"
,
COMMAND_RESPOND_ERROR
,
mpg123_currentSong
,
errorBuffer
);
mpg123kill
();
return
1
;
}
...
...
@@ -344,6 +351,7 @@ int mpg123processMessages() {
if
(
!
mpg123_leavePlay
)
{
mpg123_leavePlay
=
1
;
mpg123_error
=
1
;
}
mpg123_done
=
1
;
}
else
if
(
mpg123_state
==
PLAYER_STATE_PLAY
&&
atoi
(
c
[
1
])
==
PLAYER_STATE_PAUSE
)
{
mpg123_leavePause
=
1
;
...
...
@@ -365,6 +373,7 @@ int mpg123processMessages() {
mpg123_error
=
1
;
mpg123_leavePlay
=
1
;
}
if
(
mpg123_state
==
PLAYER_STATE_PAUSE
)
mpg123_lastFrame
=
time
(
NULL
);
mpg123_elapsedTime
=
mpg123_reportedElapsedTime
+
time
(
NULL
)
-
mpg123_lastFrame
;
if
(
!
mpg123_error
&&
mpg123_leavePlay
&&
mpg123_elapsedTime
>=
mpg123_totalTime
)
{
mpg123stop
(
stderr
);
...
...
ogg.c
View file @
82ba78e0
...
...
@@ -18,6 +18,7 @@
#ifdef HAVE_OGG
#include "ogg.h"
#include "ogg_decode.h"
#include "command.h"
#include "interface.h"
#include "playlist.h"
...
...
@@ -38,22 +39,8 @@
#include <vorbis/vorbisfile.h>
#include <ao/ao.h>
#define OGG_ERROR "@ERROR"
#define OGG_START "@START"
#define OGG_TIME "@TIME"
#define OGG_DONE "@DONE"
#define OGG_PAUSE_GOT "@PAUSE_GOT"
#define OGG_STOP "stop"
#define OGG_PAUSE "pause"
#define INPUT_BUFFER_SIZE 80
#define MAX_BUFFER_LENGTH 1024
char
pcmout
[
64
];
char
input
[
INPUT_BUFFER_SIZE
+
1
];
int
ogg_pid
=
0
;
int
ogg_state
=
PLAYER_STATE_STOP
;
int
ogg_elapsedTime
=
0
;
...
...
@@ -66,93 +53,6 @@ char ogg_buffer[MAX_BUFFER_LENGTH+1];
int
ogg_bufferLength
=
0
;
char
ogg_currentSong
[
MAXPATHLEN
+
1
]
=
"
\0
"
;
int
ogg_GO
(
char
*
file
,
FILE
*
in
,
FILE
*
out
)
{
OggVorbis_File
vf
;
int
eof
=
0
;
int
current_section
;
ao_device
*
device
;
ao_sample_format
format
;
int
default_driver
;
FILE
*
oggfp
;
int
pause
=
0
;
long
ret
;
float
last_tell
=
0
;
ao_initialize
();
default_driver
=
ao_default_driver_id
();
if
(
!
(
oggfp
=
fopen
(
file
,
"r"
))
||
ov_open
(
oggfp
,
&
vf
,
NULL
,
0
)
<
0
)
{
fprintf
(
out
,
"%s Input does not appear to be an Ogg bitstream.
\n
"
,
OGG_ERROR
);
fflush
(
out
);
return
-
1
;
}
{
vorbis_info
*
vi
=
ov_info
(
&
vf
,
-
1
);
format
.
bits
=
16
;
format
.
channels
=
vi
->
channels
;
format
.
rate
=
vi
->
rate
;
format
.
byte_format
=
AO_FMT_LITTLE
;
}
device
=
ao_open_live
(
default_driver
,
&
format
,
NULL
);
if
(
device
==
NULL
)
{
fprintf
(
out
,
"%s Error opening device.
\n
"
,
OGG_ERROR
);
fflush
(
out
);
return
-
1
;
}
fprintf
(
out
,
"%s
\n
"
,
OGG_START
);
fprintf
(
out
,
"%s %f %f
\n
"
,
OGG_TIME
,
last_tell
,
ov_time_total
(
&
vf
,
-
1
));
while
(
!
eof
)
{
if
(
!
pause
)
ret
=
ov_read
(
&
vf
,
pcmout
,
sizeof
(
pcmout
),
0
,
2
,
1
,
&
current_section
);
if
(
ret
==
0
)
{
eof
=
1
;
}
else
if
(
ret
<
0
)
{
}
else
if
(
!
pause
)
{
ao_play
(
device
,
pcmout
,
sizeof
(
pcmout
));
if
(
ov_time_tell
(
&
vf
)
-
last_tell
>=
0
.
2
)
{
last_tell
=
ov_time_tell
(
&
vf
);
fprintf
(
out
,
"%s %f %f
\n
"
,
OGG_TIME
,
last_tell
,
ov_time_total
(
&
vf
,
-
1
));
fflush
(
out
);
}
}
{
static
fd_set
fds
;
static
struct
timeval
tv
;
tv
.
tv_sec
=
0
;
tv
.
tv_usec
=
0
;
FD_ZERO
(
&
fds
);
FD_SET
(
fileno
(
in
),
&
fds
);
fflush
(
in
);
if
(
select
(
fileno
(
in
)
+
1
,
&
fds
,
NULL
,
NULL
,
&
tv
))
{
myFgets
(
input
,
INPUT_BUFFER_SIZE
,
in
);
if
(
strcasecmp
(
OGG_STOP
,
input
)
==
0
)
{
eof
=
1
;
}
else
if
(
strcasecmp
(
OGG_PAUSE
,
input
)
==
0
)
{
fprintf
(
out
,
"%s
\n
"
,
OGG_PAUSE_GOT
);
fflush
(
out
);
pause
=
!
pause
;;
}
}
}
if
(
pause
)
usleep
(
1000
);
}
ao_close
(
device
);
ao_shutdown
();
ov_clear
(
&
vf
);
fprintf
(
out
,
"%s
\n
"
,
OGG_DONE
);
return
0
;
}
void
ogg_sigHandler
(
int
signal
)
{
if
(
signal
==
SIGCHLD
)
{
wait3
(
NULL
,
WNOHANG
,
NULL
);
...
...
@@ -200,7 +100,7 @@ int oggInit(char * file) {
in
=
fdopen
(
fd_send
[
1
],
"r"
);
out
=
fdopen
(
fd_recv
[
1
],
"w"
);
if
(
ogg_
GO
(
file
,
in
,
out
)
<
0
)
{
if
(
ogg_
decode
(
file
,
in
,
out
)
<
0
)
{
fprintf
(
stderr
,
"%s Problems spawning ogg
\n
"
,
COMMAND_RESPOND_ERROR
);
fclose
(
in
);
fclose
(
out
);
...
...
ogg_decode.c
0 → 100644
View file @
82ba78e0
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://musicpd.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_OGG
#include "ogg_decode.h"
#include "command.h"
#include "utils.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <vorbis/vorbisfile.h>
#include <ao/ao.h>
#define CHUNK_SIZE 256
#define BUFFERED_CHUNKS 8192
/* 2 MB of buffer */
#define PLAY_SIZE 64
#define TIME_TELL_INTERVAL 0.2
#define INPUT_BUFFER_SIZE 80
int
decode_pid
=
0
;
int
decode_done
=
0
;
void
ogg_decode_parentSigHandler
(
int
sig
)
{
if
(
sig
==
SIGCHLD
)
{
wait3
(
NULL
,
WNOHANG
,
NULL
);
decode_pid
=
0
;
decode_done
=
1
;
}
}
/* ogg_decode w/ buffering
* this will fork another process
* child process does decoding
* parent process does buffering && playing audio
*/
int
ogg_decode
(
char
*
file
,
FILE
*
in
,
FILE
*
out
)
{
OggVorbis_File
vf
;
ao_device
*
device
;
ao_sample_format
format
;
int
default_driver
;
float
time_total
;
FILE
*
oggfp
;
int
fd_chunks
[
2
],
fd_times
[
2
];
if
(
!
(
oggfp
=
fopen
(
file
,
"r"
))
||
ov_open
(
oggfp
,
&
vf
,
NULL
,
0
)
<
0
)
{
fprintf
(
out
,
"%s Input does not appear to be an Ogg bitstream.
\n
"
,
OGG_ERROR
);
fflush
(
out
);
return
-
1
;
}
{
vorbis_info
*
vi
=
ov_info
(
&
vf
,
-
1
);
format
.
bits
=
16
;
format
.
channels
=
vi
->
channels
;
format
.
rate
=
vi
->
rate
;
format
.
byte_format
=
AO_FMT_LITTLE
;
}
time_total
=
ov_time_total
(
&
vf
,
-
1
);
if
(
socketpair
(
AF_UNIX
,
SOCK_STREAM
,
0
,
fd_chunks
)
<
0
)
{
fprintf
(
stderr
,
"%s ogg_decode Problems socketpair'ing
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
}
if
(
socketpair
(
AF_UNIX
,
SOCK_STREAM
,
0
,
fd_times
)
<
0
)
{
fprintf
(
stderr
,
"%s ogg_decode Problems socketpair'ing
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
}
signal
(
SIGPIPE
,
SIG_IGN
);
signal
(
SIGCHLD
,
ogg_decode_parentSigHandler
);
fflush
(
NULL
);
decode_pid
=
fork
();
if
(
decode_pid
==
0
)
{
/* CHILD */
char
chunk
[
CHUNK_SIZE
];
float
time
;
int
current_section
;
int
eof
=
0
;
fd_set
fds
;
struct
timeval
tv
;
int
start
=
1
;
long
ret
;
tv
.
tv_sec
=
0
;
tv
.
tv_usec
=
0
;
fclose
(
in
);
fclose
(
out
);
close
(
fd_chunks
[
0
]);
close
(
fd_times
[
0
]);
while
(
!
eof
)
{
ret
=
ov_read
(
&
vf
,
chunk
,
CHUNK_SIZE
,
0
,
2
,
1
,
&
current_section
);
time
=
ov_time_tell
(
&
vf
);
if
(
ret
==
0
)
eof
=
1
;
FD_ZERO
(
&
fds
);
FD_SET
(
fd_chunks
[
1
],
&
fds
);
FD_SET
(
fd_times
[
1
],
&
fds
);
while
(
!
start
&&
2
!=
select
(
FD_SETSIZE
,
NULL
,
&
fds
,
NULL
,
&
tv
))
{
usleep
(
100
);
FD_ZERO
(
&
fds
);
FD_SET
(
fd_chunks
[
1
],
&
fds
);
FD_SET
(
fd_times
[
1
],
&
fds
);
}
start
=
0
;
if
(
write
(
fd_chunks
[
1
],
chunk
,
CHUNK_SIZE
)
<
0
)
{
fprintf
(
stderr
,
"%s ogg_decode child problems writing
\n
"
,
COMMAND_RESPOND_ERROR
);
exit
(
-
1
);
}
if
(
write
(
fd_times
[
1
],
&
(
time
),
sizeof
(
float
))
<
0
)
{
fprintf
(
stderr
,
"%s ogg_decode child problems writing
\n
"
,
COMMAND_RESPOND_ERROR
);
exit
(
-
1
);
}
}
time
=
-
1
;
if
(
write
(
fd_times
[
1
],
&
(
time
),
sizeof
(
float
))
<
0
)
{
fprintf
(
stderr
,
"%s ogg_decode child problems writing
\n
"
,
COMMAND_RESPOND_ERROR
);
exit
(
-
1
);
}
ov_clear
(
&
vf
);
close
(
fd_times
[
1
]);
close
(
fd_chunks
[
1
]);
exit
(
0
);
/* END OF CHILD */
}
else
if
(
decode_pid
<
0
)
{
fprintf
(
stderr
,
"%s ogg_decode Problems fork'ing
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
}
{
/* PARENT */
float
elapsed
;
float
last_tell
=
0
;
int
pause
=
0
;
char
input
[
INPUT_BUFFER_SIZE
+
1
];
char
**
buffer
;
float
time
[
BUFFERED_CHUNKS
];
int
begin
=
0
;
int
end
=
0
;
int
wrap
=
0
;
int
playsPerChunk
=
CHUNK_SIZE
/
PLAY_SIZE
;
int
currentPlayChunk
=
0
;
int
i
;
int
quit
=
0
;
close
(
fd_chunks
[
1
]);
close
(
fd_times
[
1
]);
ov_clear
(
&
vf
);
ao_initialize
();
default_driver
=
ao_default_driver_id
();
device
=
ao_open_live
(
default_driver
,
&
format
,
NULL
);
if
(
device
==
NULL
)
{
fprintf
(
out
,
"%s Error opening device.
\n
"
,
OGG_ERROR
);
fflush
(
out
);
close
(
fd_chunks
[
0
]);
close
(
fd_times
[
0
]);
kill
(
decode_pid
,
SIGTERM
);
wait
(
NULL
);
return
-
1
;
}
buffer
=
malloc
(
sizeof
(
char
*
)
*
BUFFERED_CHUNKS
);
for
(
i
=
0
;
i
<
BUFFERED_CHUNKS
;
i
++
)
{
buffer
[
i
]
=
malloc
(
sizeof
(
char
)
*
CHUNK_SIZE
);
}
fprintf
(
out
,
"%s
\n
"
,
OGG_START
);
fprintf
(
out
,
"%s %f %f
\n
"
,
OGG_TIME
,
last_tell
,
time_total
);
while
(
!
quit
)
{
if
((
begin
!=
end
||
!
wrap
)
&&
!
decode_done
)
{
static
fd_set
fds
;
static
struct
timeval
tv
;
tv
.
tv_sec
=
0
;
tv
.
tv_usec
=
0
;
FD_ZERO
(
&
fds
);
FD_SET
(
fd_times
[
0
],
&
fds
);
if
(
select
(
FD_SETSIZE
,
&
fds
,
NULL
,
NULL
,
&
tv
))
{
read
(
fd_times
[
0
],
&
(
time
[
end
]),
sizeof
(
float
));
if
(
time
[
end
]
<
0
)
decode_done
=
1
;
else
{
read
(
fd_chunks
[
0
],
buffer
[
end
],
CHUNK_SIZE
);
}
end
++
;
if
(
end
>=
BUFFERED_CHUNKS
)
{
end
=
0
;
wrap
=
1
;
}
}
}
if
(
begin
==
end
&&
!
wrap
&&
decode_done
)
quit
=
1
;
if
((
begin
!=
end
||
wrap
)
&&
!
pause
)
{
if
(
currentPlayChunk
==
0
)
elapsed
=
time
[
begin
];
ao_play
(
device
,
buffer
[
begin
]
+
currentPlayChunk
*
PLAY_SIZE
,
PLAY_SIZE
);
currentPlayChunk
++
;
if
(
currentPlayChunk
>=
playsPerChunk
)
{
currentPlayChunk
=
0
;
begin
++
;
if
(
begin
>=
BUFFERED_CHUNKS
)
{
begin
=
0
;
wrap
=
0
;
}
}
if
(
elapsed
-
last_tell
>=
TIME_TELL_INTERVAL
)
{
last_tell
=
elapsed
;
fprintf
(
out
,
"%s %f %f
\n
"
,
OGG_TIME
,
last_tell
,
time_total
);
fflush
(
out
);
}
}
{
static
fd_set
fds
;
static
struct
timeval
tv
;
tv
.
tv_sec
=
0
;
tv
.
tv_usec
=
0
;
FD_ZERO
(
&
fds
);
FD_SET
(
fileno
(
in
),
&
fds
);
fflush
(
in
);
if
(
select
(
fileno
(
in
)
+
1
,
&
fds
,
NULL
,
NULL
,
&
tv
))
{
myFgets
(
input
,
INPUT_BUFFER_SIZE
,
in
);
if
(
strcasecmp
(
OGG_STOP
,
input
)
==
0
)
{
quit
=
1
;
}
else
if
(
strcasecmp
(
OGG_PAUSE
,
input
)
==
0
)
{
fprintf
(
out
,
"%s
\n
"
,
OGG_PAUSE_GOT
);
fflush
(
out
);
pause
=
!
pause
;
}
}
}
if
(
pause
)
usleep
(
1000
);
}
if
(
decode_pid
>
0
)
{
kill
(
decode_pid
,
SIGTERM
);
wait
(
NULL
);
}
for
(
i
=
0
;
i
<
BUFFERED_CHUNKS
;
i
++
)
{
free
(
buffer
[
i
]);
}
free
(
buffer
);
close
(
fd_times
[
0
]);
close
(
fd_chunks
[
0
]);
fprintf
(
out
,
"%s
\n
"
,
OGG_DONE
);
/* END OF PARENT */
}
return
0
;
}
#endif
ogg_decode.h
0 → 100644
View file @
82ba78e0
/* the Music Player Daemon (MPD)
* (c)2003 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://musicpd.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef OGG_DECODE_H
#define OGG_DECODE_H
#include <stdio.h>
#define OGG_ERROR "@ERROR"
#define OGG_START "@START"
#define OGG_TIME "@TIME"
#define OGG_DONE "@DONE"
#define OGG_PAUSE_GOT "@PAUSE_GOT"
#define OGG_STOP "stop"
#define OGG_PAUSE "pause"
int
ogg_decode
(
char
*
file
,
FILE
*
in
,
FILE
*
out
);
#endif
playlist.c
View file @
82ba78e0
...
...
@@ -30,8 +30,12 @@
#include <unistd.h>
#include <time.h>
#define PLAYLIST_STATE_STOP 0
#define PLAYLIST_STATE_PLAY 1
#define PLAYLIST_STATE_STOP 0
#define PLAYLIST_STATE_PLAY 1
#define PLAYLIST_PREV_UNLESS_ELAPSED 10
/* if a song is played more than PREV_UNLESS_ELAPSED seconds,
* 'previous' restarts playing this song ('play it again, sam')
* */
Playlist
playlist
;
char
playlistDir
[
MAXPATHLEN
+
1
];
...
...
@@ -180,6 +184,11 @@ void nextSongInPlaylistIfPlayerStopped() {
}
int
nextSongInPlaylist
(
FILE
*
fp
)
{
if
(
playlist_state
!=
PLAYLIST_STATE_PLAY
)
{
fprintf
(
fp
,
"%s not currently playing
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
}
if
(
playlist
.
current
<
playlist
.
length
-
1
)
{
return
playPlaylist
(
fp
,
playlist
.
current
+
1
);
}
...
...
@@ -188,6 +197,27 @@ int nextSongInPlaylist(FILE * fp) {
return
0
;
}
int
previousSongInPlaylist
(
FILE
*
fp
)
{
if
(
playlist_state
!=
PLAYLIST_STATE_PLAY
)
{
fprintf
(
fp
,
"%s not currently playing
\n
"
,
COMMAND_RESPOND_ERROR
);
return
-
1
;
}
if
(
getPlayerElapsedTime
()
>
PLAYLIST_PREV_UNLESS_ELAPSED
)
{
return
playPlaylist
(
fp
,
playlist
.
current
);
}
else
{
if
(
playlist
.
current
>
0
)
{
return
playPlaylist
(
fp
,
playlist
.
current
-
1
);
}
else
{
return
playPlaylist
(
fp
,
playlist
.
current
);
}
}
return
0
;
}
int
shufflePlaylist
(
FILE
*
fp
)
{
int
i
;
int
ri
;
...
...
@@ -255,7 +285,7 @@ int loadPlaylist(FILE * fp, char * file) {
int
slength
=
0
;
if
((
fileP
=
fopen
(
file
,
"r"
))
==
NULL
)
{
fprintf
(
fp
,
"%s Problems opening file
\n
"
,
COMMAND_RESPOND_ERROR
);
fprintf
(
fp
,
"%s Problems opening file
\"
%s
\"\n
"
,
COMMAND_RESPOND_ERROR
,
file
);
return
-
1
;
}
...
...
playlist.h
View file @
82ba78e0
...
...
@@ -53,6 +53,8 @@ int playPlaylist(FILE * fp, int song);
int
nextSongInPlaylist
(
FILE
*
fp
);
int
previousSongInPlaylist
(
FILE
*
fp
);
int
shufflePlaylist
(
FILE
*
fp
);
int
savePlaylist
(
FILE
*
fp
,
char
*
file
);
...
...
tables.c
View file @
82ba78e0
...
...
@@ -27,21 +27,22 @@
#define TABLES_ALBUM "album"
#define TABLES_ARTIST "artist"
#define TABLES_TITLE "title"
#define TABLES_FILENAME "filename"
List
*
albumTable
;
List
*
artistTable
;
List
*
title
Table
;
List
*
song
Table
;
void
initTables
()
{
albumTable
=
makeList
(
freeList
);
artistTable
=
makeList
(
freeList
);
title
Table
=
makeList
(
NULL
);
song
Table
=
makeList
(
NULL
);
}
void
closeTables
()
{
freeList
(
albumTable
);
freeList
(
artistTable
);
freeList
(
title
Table
);
freeList
(
song
Table
);
}
void
addSongToAlbumTable
(
Song
*
song
)
{
...
...
@@ -73,9 +74,7 @@ void addSongToArtistTable(Song * song) {
}
void
addSongToSongTable
(
Song
*
song
)
{
if
(
!
song
->
tag
)
return
;
if
(
!
song
->
tag
->
title
)
return
;
insertInList
(
titleTable
,
song
->
file
,
song
);
insertInList
(
songTable
,
song
->
file
,
song
);
}
void
addSongToTables
(
Song
*
song
)
{
...
...
@@ -172,15 +171,17 @@ int searchForSongsInArtistTable(FILE * fp,char * search) {
return
ret
;
}
int
searchForSongsIn
TitleTab
le
(
FILE
*
fp
,
char
*
search
)
{
int
searchForSongsIn
SongTableByTit
le
(
FILE
*
fp
,
char
*
search
)
{
Song
*
song
;
ListNode
*
node
=
title
Table
->
firstNode
;
ListNode
*
node
=
song
Table
->
firstNode
;
int
ret
=
-
1
;
char
*
dup
;
char
*
dupSearch
=
strDupToUpper
(
search
);
while
(
node
)
{
song
=
(
Song
*
)
node
->
data
;
if
(
!
song
->
tag
)
break
;
if
(
!
song
->
tag
->
title
)
break
;
dup
=
strDupToUpper
(
song
->
tag
->
title
);
if
(
strstr
(
dup
,
dupSearch
))
{
if
(
printSongInfo
(
fp
,
song
)
<
0
)
{
...
...
@@ -200,6 +201,34 @@ int searchForSongsInTitleTable(FILE * fp,char * search) {
return
ret
;
}
int
searchForSongsInSongTableByFilename
(
FILE
*
fp
,
char
*
search
)
{
Song
*
song
;
ListNode
*
node
=
songTable
->
firstNode
;
int
ret
=
-
1
;
char
*
dup
;
char
*
dupSearch
=
strDupToUpper
(
search
);
while
(
node
)
{
song
=
(
Song
*
)
node
->
data
;
dup
=
strDupToUpper
(
song
->
file
);
if
(
strstr
(
dup
,
dupSearch
))
{
if
(
printSongInfo
(
fp
,
song
)
<
0
)
{
free
(
dup
);
free
(
dupSearch
);
return
-
1
;
}
ret
=
0
;
}
free
(
dup
);
node
=
node
->
nextNode
;
}
free
(
dupSearch
);
if
(
ret
<
0
)
fprintf
(
fp
,
"%s no songs found
\n
"
,
COMMAND_RESPOND_ERROR
);
return
ret
;
}
int
searchForSongsInTable
(
FILE
*
fp
,
char
*
table
,
char
*
search
)
{
if
(
strcmp
(
table
,
TABLES_ALBUM
)
==
0
)
{
return
searchForSongsInAlbumTable
(
fp
,
search
);
...
...
@@ -208,7 +237,10 @@ int searchForSongsInTable(FILE * fp, char * table, char * search) {
return
searchForSongsInArtistTable
(
fp
,
search
);
}
else
if
(
strcmp
(
table
,
TABLES_TITLE
)
==
0
)
{
return
searchForSongsInTitleTable
(
fp
,
search
);
return
searchForSongsInSongTableByTitle
(
fp
,
search
);
}
else
if
(
strcmp
(
table
,
TABLES_FILENAME
)
==
0
)
{
return
searchForSongsInSongTableByFilename
(
fp
,
search
);
}
fprintf
(
fp
,
"%s unkown table
\n
"
,
COMMAND_RESPOND_ERROR
);
...
...
@@ -241,14 +273,14 @@ void removeSongFromArtistTable(Song * song) {
}
}
void
removeSongFrom
Title
Table
(
Song
*
song
)
{
deleteFromList
(
title
Table
,
song
->
file
);
void
removeSongFrom
Song
Table
(
Song
*
song
)
{
deleteFromList
(
song
Table
,
song
->
file
);
}
void
removeASongFromTables
(
Song
*
song
)
{
removeSongFromAlbumTable
(
song
);
removeSongFromArtistTable
(
song
);
removeSongFrom
Title
Table
(
song
);
removeSongFrom
Song
Table
(
song
);
}
void
removeSongsFromTables
(
SongList
*
songList
)
{
...
...
@@ -261,3 +293,16 @@ void removeSongsFromTables(SongList * songList) {
node
=
node
->
nextNode
;
}
}
int
printAllSongsInSongTable
(
FILE
*
fp
)
{
Song
*
song
;
ListNode
*
node
=
songTable
->
firstNode
;
while
(
node
)
{
song
=
(
Song
*
)
node
->
data
;
fprintf
(
fp
,
"file: %s
\n
"
,
song
->
file
);
node
=
node
->
nextNode
;
}
return
0
;
}
tables.h
View file @
82ba78e0
...
...
@@ -30,10 +30,12 @@ void addSongToTables(Song * song);
int
findAndPrintSongsInTable
(
FILE
*
fp
,
char
*
table
,
char
*
find
);
int
searchForSongsInTable
(
FILE
*
fp
,
char
*
table
,
char
*
find
);
int
searchForSongsInTable
(
FILE
*
fp
,
char
*
table
,
char
*
find
);
void
removeSongsFromTables
(
SongList
*
songList
);
void
removeASongFromTables
(
Song
*
song
);
int
printAllSongsInSongTable
(
FILE
*
fp
);
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment