Commit 1e912f80 authored by Led's avatar Led

0.5.2

parents
Music Player Daemon - Commands
This document is intended for client developers, not end users.
Format:
-------
If arguments contain spaces, they should be surrounded by double quotation
marks, ".
command <type arg1> <type arg2> ...
explanation: w/ arg1 and arg2
Command Completion:
-------------------
A command returns "OK\n" on completeion or "ACK some error\n" on failure.
These denote the end of command execution.
Commands:
---------
add <string file>
add the file _file_ to the playlist
clear
clears the current playlist
close
close the connection with the mpd
delete <int song>
delete _song_ from playlist
find <string type> <string what>
finds songs in the db that are exactly _what_
_type_ should be "album", "artist", or "title"
_what_ is what to find
info <string file>
fetches id3 tag of _file_
NOTE: do not use this, meant for debugging only
kill
kill mpd
load <string name>
loads the playlist _name_.m3u from the playlist directory
ls <string directory>
list files in _directory_. _directory_ is optional.
NOTE: us this only for debugging, not meant to be used by a client.
instead use 'lsinfo'
lsinfo <string directory>
list contents of _directory_, from the db. _directory_ is optional
pause
pause/resume playing
play <int song>
being playling playlist at song number _song_
playlist
displays the current playlist
NOTE: do not use this, instead use 'playlistinfo'
playlistinfo
displays information about the current playlist
rm <string name>
removes the playlist <name>.m3u from the playlist directory
save <string name>
saves the current playlist to _name_.m3u in the playlist directory
search <string type> <string what>
same as "find" but searches for any song that contain _what_
shuffle
shuffles the current playlist
status
reports current status of player, one of the folloowing:
"stop" - player is stopped
"play <int song> <int elapsed>:<time total>"
- playing _song_ with _elapses_ seconds, and the song
is a total of _total_ seconds
"pause <int song> <int elapsed>:<tine total>"
- same as "play" but the player is currently paused
stop
stop playing
update
searches mp3 directory for new music and removes old music from the db
This diff is collapsed. Click to expand it.
Music Player Daemon (MPD) - INSTALL
Requirements
------------
mpg123 - http://www.mpg123.de (MPD has been tested with 0.59q and 0.59r)
(mpg123 is included with many distributions and supports many platforms)
Download
--------
Get the latest release from of MPD from http://musicpd.sourceforge.net
Compile
-------
1) unzip and untar the argchive
$ tar zxvf mpd-x.x.x.tar.gz
2) change to directory created
$ cd mpd-x.x.x
3) compile
$ make
Install
-------
1) copy "mpd" to a directory in path (Optional)
(as root)
$ cp mpd /usr/local/bin
Run
---
1) run mpd:
<port>: port number daemon listens on (if running as a user, this should be
greater than 1024)
<mp3 directory>: directory containing mp3's
<playlist directory>: directory where playlists will be stored (and .mpddb will
be placed)
<mpd log>: log file for mpd
<mpd err>: error log file for mpd
$ mpd <port> <mp3 directory> <playlist directory> <mpd log> <mpd err>
example where mpd executable is in mpd-x.x.x directory:
$ mpd-x.x.x/mpd 2100 mp3 playlists mpd.log mpd.err
Note: The first time you run mpd, it will "explore" your mp3 directory for
mp3's.
Using MPD
---------
You can download a web interface (phpMp) to MPD at
http://musicpd.sourceforge.net .
MPD can be interfaced directly using telnet (see command.c, if you are brave).
EXEC = mpd
CC = gcc
CFLAGS = -Wall
OFLAGS = -Wall
DFLAGS = -MM
SOURCES = main.c buffer2array.c mpg123.c interface.c command.c playlist.c ls.c \
info.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
OBJECTS = $(SOURCES:.c=.o)
DEPENDFILE =Makefile.depend
all: $(EXEC)
$(EXEC): $(OBJECTS)
$(CC) $(OFLAGS) -o $(EXEC) $(OBJECTS)
deps:
$(CC) $(DFLAGS) $(SOURCES) > $(DEPENDFILE)
-include $(DEPENDFILE)
clean:
rm -f $(EXEC) $(OBJECTS)
cleandeps:
rm -f $(DEPENDFILE)
cleanall: clean cleandeps
Music Player Daemon (MPD)
http://musicpd.sourceforge.net
A daemon for playing music (currently mp3's). Music is played through the
server's audio device. The daemon stores info about all availabe music, and
this info can be easily searched and retrieved. Player control, info retrieval,
and playlist management can all be managed remotely.
To install MPD, see INSTALL.
MPD is released under the GNU Public License.
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
For the full license, see COPYING.
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "buffer2array.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int buffer2array(char * buffer, char *** array) {
int bufferLength = strlen(buffer);
int quotes = 0;
int count = 0;
int i;
int curr;
char * markArray = malloc(sizeof(char)*(bufferLength+1));
int * beginArray;
for(curr=0;curr<bufferLength;curr++) {
if(!quotes && buffer[curr]==' ') {
markArray[curr] = '0';
}
else if(buffer[curr] == '\"') {
if(curr>0 && buffer[curr-1]!='\\') {
quotes = quotes?0:1;
markArray[curr] = '0';
}
else {
markArray[curr] = '1';
}
}
else {
markArray[curr] = '1';
}
if(markArray[curr]=='1') {
if(curr>0) {
if(markArray[curr-1]=='0') {
count++;
}
}
else {
count++;
}
}
}
markArray[bufferLength] = '\0';
beginArray = malloc(sizeof(int)*count);
(*array) = malloc(sizeof(char *)*count);
count = 0;
for(curr=0;curr<bufferLength;curr++) {
if(markArray[curr]=='1') {
if(curr>0) {
if(markArray[curr-1]=='0') {
beginArray[count++] = curr;
}
}
else {
beginArray[count++] = curr;
}
}
else {
buffer[curr] = '\0';
}
}
for(i=0;i<count;i++) {
int len = strlen(buffer+beginArray[i])+1;
int arrayCurr = 0;
(*array)[i] = malloc(sizeof(char)*len);
for(curr=beginArray[i];buffer[curr]!='\0';curr++) {
if(buffer[curr]=='\\') {
if(buffer[curr+1]!='\0') {
curr++;
}
}
(*array)[i][arrayCurr++] = buffer[curr];
}
(*array)[i][arrayCurr] = '\0';
}
free(markArray);
free(beginArray);
return count;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 BUFFER_2_ARRAY_H
#define BUFFER_2_ARRAY_H
int buffer2array(char * buffer, char *** array);
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "command.h"
#include "mpg123.h"
#include "playlist.h"
#include "ls.h"
#include "info.h"
#include "directory.h"
#include "tables.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define COMMAND_PLAY "play"
#define COMMAND_STOP "stop"
#define COMMAND_PAUSE "pause"
#define COMMAND_STATUS "status"
#define COMMAND_KILL "kill"
#define COMMAND_CLOSE "close"
#define COMMAND_ADD "add"
#define COMMAND_DELETE "delete"
#define COMMAND_PLAYLIST "playlist"
#define COMMAND_SHUFFLE "shuffle"
#define COMMAND_CLEAR "clear"
#define COMMAND_SAVE "save"
#define COMMAND_LOAD "load"
#define COMMAND_LS "ls"
#define COMMAND_LSINFO "lsinfo"
#define COMMAND_RM "rm"
#define COMMAND_INFO "info"
#define COMMAND_PLAYLISTINFO "playlistinfo"
#define COMMAND_FIND "find"
#define COMMAND_SEARCH "search"
#define COMMAND_UPDATE "update"
extern Playlist playlist;
int commandStatus(FILE * fp,int argArrayLength, char ** argArray) {
char * state;
if(argArrayLength!=1) {
fprintf(fp,"%s Wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
switch(mpg123_state) {
case MPG123_STATE_STOP:
state = strdup(COMMAND_STOP);
break;
case MPG123_STATE_PAUSE:
state = strdup(COMMAND_PAUSE);
break;
case MPG123_STATE_PLAY:
state = strdup(COMMAND_PLAY);
break;
}
if(mpg123_state>0) {
fprintf(fp,"%s %i %i:%i\n",state,playlist.current,mpg123_elapsedTime,mpg123_totalTime);
}
else {
fprintf(fp,"%s\n",state);
}
free(state);
return 0;
}
int processCommand(FILE * fp, int argArrayLength, char ** argArray) {
if(argArrayLength==0) {
return 0;
}
if(0==strcmp(argArray[0],COMMAND_PLAY)) {
int song;
char * test;
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;
}
return playPlaylist(fp,song);
}
else if(0==strcmp(argArray[0],COMMAND_STOP)) {
if(argArrayLength!=1) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return mpg123stop(fp);
}
else if(0==strcmp(argArray[0],COMMAND_PAUSE)) {
if(argArrayLength!=1) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return mpg123pause(fp);
}
else if(0==strcmp(argArray[0],COMMAND_STATUS)) {
return commandStatus(fp,argArrayLength,argArray);
}
else if(0==strcmp(argArray[0],COMMAND_KILL)) {
return COMMAND_RETURN_KILL;
}
else if(0==strcmp(argArray[0],COMMAND_CLOSE)) {
return COMMAND_RETURN_CLOSE;
}
else if(0==strcmp(argArray[0],COMMAND_ADD)) {
if(argArrayLength!=2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return addToPlaylist(fp,argArray[1]);
}
else if(0==strcmp(argArray[0],COMMAND_INFO)) {
if(argArrayLength!=2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return info(fp,argArray[1]);
}
else if(0==strcmp(argArray[0],COMMAND_SAVE)) {
char * file;
int ret;
if(argArrayLength!=2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
file = malloc(strlen(playlistDir)+strlen(argArray[1])+strlen(PLAYLIST_FILE_SUFFIX)+2);
strcpy(file,playlistDir);
strcat(file,argArray[1]);
strcat(file,".");
ret = savePlaylist(fp,strcat(file,PLAYLIST_FILE_SUFFIX));
free(file);
return ret;
}
else if(0==strcmp(argArray[0],COMMAND_RM)) {
char * file;
int ret;
if(argArrayLength!=2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
file = malloc(strlen(playlistDir)+strlen(argArray[1])+strlen(PLAYLIST_FILE_SUFFIX)+2);
strcpy(file,playlistDir);
strcat(file,argArray[1]);
strcat(file,".");
ret = deletePlaylist(fp,strcat(file,PLAYLIST_FILE_SUFFIX));
free(file);
return ret;
}
else if(0==strcmp(argArray[0],COMMAND_DELETE)) {
int song;
char * test;
if(argArrayLength!=2) {
fprintf(fp,"%s wrong number of 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;
}
return deleteFromPlaylist(fp,song);
}
else if(0==strcmp(argArray[0],COMMAND_PLAYLISTINFO)) {
int song = -1;
char * test;
if(argArrayLength>2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
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;
}
}
return playlistInfo(fp,song);
}
else if(0==strcmp(argArray[0],COMMAND_PLAYLIST)) {
if(argArrayLength!=1) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return showPlaylist(fp);
}
else if(0==strcmp(argArray[0],COMMAND_SHUFFLE)) {
if(argArrayLength!=1) {
fprintf(fp,"%s too many arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return shufflePlaylist(fp);
}
else if(0==strcmp(argArray[0],COMMAND_CLEAR)) {
if(argArrayLength!=1) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return clearPlaylist(fp);
}
else if(0==strcmp(argArray[0],COMMAND_LOAD)) {
char * file;
int ret = 0;
if(argArrayLength!=2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
file = malloc(strlen(playlistDir)+strlen(argArray[1])+strlen(PLAYLIST_FILE_SUFFIX)+2);
strcpy(file,playlistDir);
strcat(file,argArray[1]);
strcat(file,".");
if(loadPlaylist(fp,strcat(file,PLAYLIST_FILE_SUFFIX))<0) ret=-1;
free(file);
return ret;
}
else if(0==strcmp(argArray[0],COMMAND_LS)) {
if(argArrayLength>2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
if(argArrayLength==1) {
if(ls(fp,NULL)<0) return -1;
else return lsPlaylists(fp);
}
else {
return ls(fp,argArray[1]);
}
}
else if(0==strcmp(argArray[0],COMMAND_LSINFO)) {
if(argArrayLength>2) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
if(argArrayLength==1) {
if(printDirectoryInfo(fp,NULL)<0) return -1;
else return lsPlaylists(fp);
}
else {
return printDirectoryInfo(fp,argArray[1]);
}
}
else if(0==strcmp(argArray[0],COMMAND_FIND)) {
if(argArrayLength!=3) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return findAndPrintSongsInTable(fp,argArray[1],argArray[2]);
}
else if(0==strcmp(argArray[0],COMMAND_SEARCH)) {
if(argArrayLength!=3) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return searchForSongsInTable(fp,argArray[1],argArray[2]);
}
else if(0==strcmp(argArray[0],COMMAND_UPDATE)) {
if(argArrayLength!=1) {
fprintf(fp,"%s wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return updateMp3Directory(fp);
}
else {
fprintf(fp,"%s Unknown command \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]);
return -1;
}
return 0;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 COMMAND_H
#define COMMAND_H
#include <stdio.h>
#define COMMAND_RETURN_KILL 10
#define COMMAND_RETURN_CLOSE 20
#define COMMAND_RESPOND_ERROR "ACK"
#define COMMAND_RESPOND_OK "OK"
int processCommand(FILE * fp, int argArrayLength, char ** argArray);
#endif
This diff is collapsed. Click to expand it.
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 DIRECTORY_H
#define DIRECTORY_H
#include <stdio.h>
#include <sys/param.h>
extern char directorydb[MAXPATHLEN+1];
void initMp3Directory();
void closeMp3Directory();
int printDirectoryInfo(FILE * fp, char * dirname);
int writeDirectoryDB();
int readDirectoryDB();
size_t getDirectoryLine(char ** buffer, int * size, FILE * fp);
int updateMp3Directory(FILE * fp);
#endif
This library was written by Samuel Abels (sam@manicsadness.com).
If you have any questions, feel free to contact me, or visit the project homepage at
http://software.manicsadness.com
----------------
The library is very easy to use.
It is meant to be compiled directly into your project.
Example:
#include "genre.h"
#include "lib_id3v1.h"
main()
{
id3Tag tag;
strcpy (tag.artist, "Myartist");
strcpy (tag.album, "Myalbum");
strcpy (tag.title, "Mysong");
strcpy (tag.track, "12");
strcpy (tag.year, "2002");
strcpy (tag.comment, "Mycomment");
strcpy (tag.genre, genre[14]);
set_id3v1tag(&tag, "/home/sam/myfile.mp3");
}
If you need more info, look into the header file, it's really simple.
/* the id3v1 library.
* (c)2002 by Samuel Abels (sam@manicsadness.com)
* This project's homepage is: http://software.manicsadness.com/cantus
*
* This library is designed for easyest possible access to id3 V1 tags.
*
* 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 GENRE_H
#define GENRE_H
#define NUM_GENRES 150
char *genre[]={
/*1*/ "Blues",
/*2*/ "Classic Rock",
/*3*/ "Country",
/*4*/ "Dance",
/*5*/ "Disco",
/*6*/ "Funk",
/*7*/ "Grunge",
/*8*/ "Hip-Hop",
/*9*/ "Jazz",
/*10*/ "Metal",
/*11*/ "New Age",
/*12*/ "Oldies",
/*13*/ "Other",
/*14*/ "Pop",
/*15*/ "R&B",
/*16*/ "Rap",
/*17*/ "Reggae",
/*18*/ "Rock",
/*19*/ "Techno",
/*20*/ "Industrial",
/*21*/ "Alternative",
/*22*/ "Ska",
/*23*/ "Death Metal",
/*24*/ "Pranks",
/*25*/ "Soundtrack",
/*26*/ "Euro-Techno",
/*27*/ "Ambient",
/*28*/ "Trip-Hop",
/*29*/ "Vocal",
/*30*/ "Jazz+Funk",
/*31*/ "Fusion",
/*32*/ "Trance",
/*33*/ "Classical",
/*34*/ "Instrumental",
/*35*/ "Acid",
/*36*/ "House",
/*37*/ "Game",
/*38*/ "Sound Clip",
/*39*/ "Gospel",
/*40*/ "Noise",
/*41*/ "AlternRock",
/*42*/ "Bass",
/*43*/ "Soul",
/*44*/ "Punk",
/*45*/ "Space",
/*46*/ "Meditative",
/*47*/ "Instrumental Pop",
/*48*/ "Instrumental Rock",
/*49*/ "Ethnic",
/*50*/ "Gothic",
/*51*/ "Darkwave",
/*52*/ "Techno-Industrial",
/*53*/ "Electronic",
/*54*/ "Pop-Folk",
/*55*/ "Eurodance",
/*56*/ "Dream",
/*57*/ "Southern Rock",
/*58*/ "Comedy",
/*59*/ "Cult",
/*60*/ "Gangsta",
/*61*/ "Top 40",
/*62*/ "Christian Rap",
/*63*/ "Pop/Funk",
/*64*/ "Jungle",
/*65*/ "Native American",
/*66*/ "Cabaret",
/*67*/ "New Wave",
/*68*/ "Psychadelic",
/*69*/ "Rave",
/*70*/ "Showtunes",
/*71*/ "Trailer",
/*72*/ "Lo-Fi",
/*73*/ "Tribal",
/*74*/ "Acid Punk",
/*75*/ "Acid Jazz",
/*76*/ "Polka",
/*77*/ "Retro",
/*78*/ "Musical",
/*79*/ "Rock & Roll",
/*80*/ "Hard Rock",
// WinAmp extensions:
/*81*/ "Folk",
/*82*/ "Folk-Rock",
/*83*/ "National Folk",
/*84*/ "Swing",
/*85*/ "Fast Fusion",
/*86*/ "Bebob",
/*87*/ "Latin",
/*88*/ "Revival",
/*89*/ "Celtic",
/*90*/ "Bluegrass",
/*91*/ "Avantgarde",
/*92*/ "Gothic Rock",
/*93*/ "Progressive Rock",
/*94*/ "Psychedelic Rock",
/*95*/ "Symphonic Rock",
/*96*/ "Slow Rock",
/*97*/ "Big Band",
/*98*/ "Chorus",
/*99*/ "Easy Listening",
/*100*/ "Acoustic",
/*101*/ "Humour",
/*102*/ "Speech",
/*103*/ "Chanson",
/*104*/ "Opera",
/*105*/ "Chamber Music",
/*106*/ "Sonata",
/*107*/ "Symphony",
/*108*/ "Booty Bass",
/*109*/ "Primus",
/*110*/ "Porn Groove",
/*111*/ "Satire",
/*112*/ "Slow Jam",
/*113*/ "Club",
/*114*/ "Tango",
/*115*/ "Samba",
/*116*/ "Folklore",
/*117*/ "Ballad",
/*118*/ "Power Ballad",
/*119*/ "Rhythmic Soul",
/*120*/ "Freestyle",
/*121*/ "Duet",
/*122*/ "Punk Rock",
/*123*/ "Drum Solo",
/*124*/ "A capella",
/*125*/ "Euro-House",
/*126*/ "Dance Hall",
/*127*/ "Goa",
/*128*/ "Drum & Bass",
/*129*/ "Club-House",
/*130*/ "Hardcore",
/*131*/ "Terror",
/*132*/ "Indie",
/*133*/ "BritPop",
/*134*/ "Negerpunk",
/*135*/ "Polsk Punk",
/*136*/ "Beat",
/*137*/ "Christian Gansta Rap",
/*138*/ "Heavy Metal",
/*139*/ "Black Metal",
/*140*/ "Crossover",
/*141*/ "Contemporary Christian",
/*142*/ "Christian Rock",
/*143*/ "Merengue",
/*144*/ "Salsa",
/*145*/ "Thrash Metal",
/*146*/ "Anime",
/*147*/ "Jpop",
/*148*/ "Synthpop"
};
#endif
/* the id3v1 library.
* (c)2002 by Samuel Abels (sam@manicsadness.com)
* This project's homepage is: http://software.manicsadness.com/cantus
*
* This library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include "lib_id3v1.h"
#include "genre.h"
/*
* Purpose: Reads the ID3 tag from a file.
* Parameters: tag - The structure to store the tag in, filename - The name of the file to operate on.
* Returns:
* 0 if successful,
* 1 if an error occured when opening the file
* 2 if error while reading tag.
* 3 if no TAG found.
*/
int get_id3v1_tag(id3Tag *tag, char *filename)
{
FILE *mp3file;
char *buffer = malloc(2048);
id3v1Tag *v1 = malloc(sizeof(id3v1Tag));
short int foundtag = FALSE;
int i = -1;
memset(tag, 0, sizeof(id3Tag));
memset(v1, 0, sizeof(id3v1Tag));
memset(buffer, 0, 2048);
mp3file = fopen(filename, "rb");
if (!mp3file)
return 1;
// read the last 200 bytes of the file.
// in most cases, the last 128 bytes would be enough, but some buggy tags, again...
fseek(mp3file, -200, SEEK_END);
if( !fread(buffer, 1, 400, mp3file) )
{
free(buffer);
free(v1);
fclose(mp3file);
return 2;
}
fclose(mp3file);
// parse through the raw data, if a "TAG" sign is found, we copy the raw data to a struct.
i = -1;
while( ++i <= (200-128) )
{
if( (*(buffer + i + 0) == 'T')
&& (*(buffer + i + 1) == 'A')
&& (*(buffer + i + 2) == 'G') )
{
memcpy(v1, buffer + i + 3, 125);
foundtag = TRUE;
break;
}
}
free(buffer);
if(!foundtag)
{
free(v1);
return 3;
}
strncpy(tag->title, v1->title, 30);
strncpy(tag->artist, v1->artist, 30);
strncpy(tag->album, v1->album, 30);
strncpy(tag->year, v1->year, 4);
if(v1->comment[28]=='\0' && v1->comment[29]!='\0')
{
strncpy(tag->comment, v1->comment, 28);
snprintf(tag->track, 3, "%i", v1->comment[29]);
tag->comment[29] = '\0';
}
else
{
strncpy(tag->comment, v1->comment, 30);
tag->comment[30] = '\0';
}
if( v1->genre > 148 )
strncpy(tag->genre, genre[12], 511);
else
strncpy(tag->genre, genre[v1->genre], 511);
free(v1);
return 0;
}
/*
* Purpose: Writes the ID3 tag to the file.
* Parameters: tag - The tag to write, filename - The name of the file to operate on.
* Returns:
* 0 if successful,
* 1 if an error occured when opening the file for reading
* 2 if error while reading whole file.
* 3 if an error occured while writing the whole file
* 4 if error while opening file for tagadding.
* 5 if error while writing the tag.
*/
int set_id3v1_tag(id3Tag *tag, char *filename)
{
FILE *mp3file;
id3v1Tag *v1;
int i = 0;
del_id3v1_tag(filename);
// Prepare users data for writing
v1 = malloc(sizeof(id3v1Tag));
memcpy(v1->title, tag->title, 30);
memcpy(v1->artist, tag->artist, 30);
memcpy(v1->album, tag->album, 30);
memcpy(v1->year, tag->year, 4);
if(tag->track)
{
memcpy(v1->comment, tag->comment, 28);
v1->comment[28]='\0';
*(v1->comment+29) = atoi(tag->track);
}
else
{
memcpy(v1->comment, tag->comment, 30);
}
// Find the genre number
i = -1;
while(genre[++i])
{
if(strcmp(genre[i], tag->genre) == 0)
break;
}
// ...or set the genre to "other"
if(!genre[i])
i = 12;
v1->genre = i;
mp3file = fopen(filename, "r+b");
if (!mp3file)
{
free(v1);
return 4;
}
// now add the new tag
fseek(mp3file, 0, SEEK_END);
fputc('T', mp3file);
fputc('A', mp3file);
fputc('G', mp3file);
if (!fwrite(v1, 1, sizeof(id3v1Tag), mp3file))
{
free(v1);
fclose(mp3file);
return 5;
}
fclose(mp3file);
free(v1);
return 0;
}
/*
* Name says it all.
* Returns:
* 0 if successful,
* 1 if an error occured when opening the file
* 2 if error while reading file.
* 3 if no TAG found.
*/
int del_id3v1_tag(char *filename)
{
FILE *mp3stream;
int mp3file;
long i = 0, len;
char buffer[400];
// Find length of the file
mp3stream = fopen(filename, "r+b");
if(!mp3stream)
return 1;
fseek(mp3stream, 0, SEEK_END);
len = ftell(mp3stream);
fclose(mp3stream);
// Open file for writing
mp3file = open(filename, O_RDWR);
if(mp3file == -1)
return 1;
// if there is an existing tag, delete it.
memset (buffer, 0, 400);
// read the last 400 bytes of the file.
// in most cases, the last 128 bytes would be enough, but some buggy tags, again...
lseek (mp3file, -400L, SEEK_END);
if ( read(mp3file, buffer, 400) < 400 )
{
close(mp3file);
return 2;
}
i = -1;
while ( ++i <= 400 )
{
if( buffer[i] == 'T'
&& buffer[i + 1] == 'A'
&& buffer[i + 2] == 'G' )
{
ftruncate (mp3file, len - (400 - i) );
break;
}
}
close(mp3file);
return 0;
}
/* the id3v1 library.
* (c)2002 by Samuel Abels (sam@manicsadness.com)
* This project's homepage is: http://software.manicsadness.com/cantus
*
* This library is designed for easyest possible access to id3 V1 tags.
*
* 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 FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef id3Tag_def
#define id3Tag_def
typedef struct id3Tag_s
{
char title[1024];
char artist[1024];
char album[1024];
char year[5];
char comment[1024];
char track[10];
char genre[512];
unsigned int size;
short int has_footer;
} id3Tag;
typedef struct id3v1Tag_s
{
char title[30];
char artist[30];
char album[30];
char year[4];
char comment[30];
unsigned char genre;
} id3v1Tag;
#endif
int get_id3v1_tag(id3Tag *tag, char *filename);
int set_id3v1_tag(id3Tag *tag, char *filename);
int del_id3v1_tag(char *filename);
This library was written by Samuel Abels (sam@manicsadness.com).
The charset conversion were taken from EasyTag, but he took it from XMMS.
If you have any questions, feel free to contact me, or visit the project homepage at
http://software.manicsadness.com
Authors
------------
Samuel Abels (sam@manicsadness.com)
Patches
------------
Matt McClure (mlm@aya.yale.edu)
----------------
The library is very easy to use.
It is meant to be compiled directly into your project.
Example:
#include "genre.h"
#include "lib_id3v1.h"
main()
{
id3Tag tag;
strcpy (tag.artist, "Myartist");
strcpy (tag.album, "Myalbum");
strcpy (tag.title, "Mysong");
strcpy (tag.track, "12");
strcpy (tag.year, "2002");
strcpy (tag.comment, "Mycomment");
strcpy (tag.genre, "Mygenre");
set_id3v2tag(&tag, "/home/sam/myfile.mp3");
}
If you need more info, look into the header file, it's really simple.
/* charset.h - 2001/12/04 */
/*
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 2000-2002 Jerome Couderc <j.couderc@ifrance.com>
*
* 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 FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
* Standard gettext macros.
*/
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(String) gettext (String)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define N_(String) (String)
#endif
#ifndef DLL_H
#define DLL_H
typedef struct DLL_s
{
void *prev;
void *data;
void *next;
} DLL;
#endif
#ifndef __CHARSET_H__
#define __CHARSET_H__
/***************
* Declaration *
***************/
typedef struct {
char *charset_title;
char *charset_name;
} CharsetInfo;
/* translated charset titles */
extern const CharsetInfo charset_trans_array[];
/**************
* Prototypes *
**************/
//static gchar* get_current_charset (void);
/* Used for ogg tags */
char* convert_to_utf8 (const char *string);
char* convert_from_utf8 (const char *string);
char* convert_from_file_to_user (const char *string);
char* convert_from_user_to_file (const char *string);
DLL *Charset_Create_List (void);
char *Charset_Get_Name_From_Title (char *charset_title);
char *Charset_Get_Title_From_Name (char *charset_name);
short int test_conversion_charset (char *from, char *to);
#endif /* __CHARSET_H__ */
/* the id3v1 library.
* (c)2002 by Samuel Abels (sam@manicsadness.com)
* This project's homepage is: http://software.manicsadness.com/cantus
*
* This library is designed for easyest possible access to id3 V1 tags.
*
* 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 GENRE_H
#define GENRE_H
#define NUM_GENRES 150
char *genre[]={
/*1*/ "Blues",
/*2*/ "Classic Rock",
/*3*/ "Country",
/*4*/ "Dance",
/*5*/ "Disco",
/*6*/ "Funk",
/*7*/ "Grunge",
/*8*/ "Hip-Hop",
/*9*/ "Jazz",
/*10*/ "Metal",
/*11*/ "New Age",
/*12*/ "Oldies",
/*13*/ "Other",
/*14*/ "Pop",
/*15*/ "R&B",
/*16*/ "Rap",
/*17*/ "Reggae",
/*18*/ "Rock",
/*19*/ "Techno",
/*20*/ "Industrial",
/*21*/ "Alternative",
/*22*/ "Ska",
/*23*/ "Death Metal",
/*24*/ "Pranks",
/*25*/ "Soundtrack",
/*26*/ "Euro-Techno",
/*27*/ "Ambient",
/*28*/ "Trip-Hop",
/*29*/ "Vocal",
/*30*/ "Jazz+Funk",
/*31*/ "Fusion",
/*32*/ "Trance",
/*33*/ "Classical",
/*34*/ "Instrumental",
/*35*/ "Acid",
/*36*/ "House",
/*37*/ "Game",
/*38*/ "Sound Clip",
/*39*/ "Gospel",
/*40*/ "Noise",
/*41*/ "AlternRock",
/*42*/ "Bass",
/*43*/ "Soul",
/*44*/ "Punk",
/*45*/ "Space",
/*46*/ "Meditative",
/*47*/ "Instrumental Pop",
/*48*/ "Instrumental Rock",
/*49*/ "Ethnic",
/*50*/ "Gothic",
/*51*/ "Darkwave",
/*52*/ "Techno-Industrial",
/*53*/ "Electronic",
/*54*/ "Pop-Folk",
/*55*/ "Eurodance",
/*56*/ "Dream",
/*57*/ "Southern Rock",
/*58*/ "Comedy",
/*59*/ "Cult",
/*60*/ "Gangsta",
/*61*/ "Top 40",
/*62*/ "Christian Rap",
/*63*/ "Pop/Funk",
/*64*/ "Jungle",
/*65*/ "Native American",
/*66*/ "Cabaret",
/*67*/ "New Wave",
/*68*/ "Psychadelic",
/*69*/ "Rave",
/*70*/ "Showtunes",
/*71*/ "Trailer",
/*72*/ "Lo-Fi",
/*73*/ "Tribal",
/*74*/ "Acid Punk",
/*75*/ "Acid Jazz",
/*76*/ "Polka",
/*77*/ "Retro",
/*78*/ "Musical",
/*79*/ "Rock & Roll",
/*80*/ "Hard Rock",
// WinAmp extensions:
/*81*/ "Folk",
/*82*/ "Folk-Rock",
/*83*/ "National Folk",
/*84*/ "Swing",
/*85*/ "Fast Fusion",
/*86*/ "Bebob",
/*87*/ "Latin",
/*88*/ "Revival",
/*89*/ "Celtic",
/*90*/ "Bluegrass",
/*91*/ "Avantgarde",
/*92*/ "Gothic Rock",
/*93*/ "Progressive Rock",
/*94*/ "Psychedelic Rock",
/*95*/ "Symphonic Rock",
/*96*/ "Slow Rock",
/*97*/ "Big Band",
/*98*/ "Chorus",
/*99*/ "Easy Listening",
/*100*/ "Acoustic",
/*101*/ "Humour",
/*102*/ "Speech",
/*103*/ "Chanson",
/*104*/ "Opera",
/*105*/ "Chamber Music",
/*106*/ "Sonata",
/*107*/ "Symphony",
/*108*/ "Booty Bass",
/*109*/ "Primus",
/*110*/ "Porn Groove",
/*111*/ "Satire",
/*112*/ "Slow Jam",
/*113*/ "Club",
/*114*/ "Tango",
/*115*/ "Samba",
/*116*/ "Folklore",
/*117*/ "Ballad",
/*118*/ "Power Ballad",
/*119*/ "Rhythmic Soul",
/*120*/ "Freestyle",
/*121*/ "Duet",
/*122*/ "Punk Rock",
/*123*/ "Drum Solo",
/*124*/ "A capella",
/*125*/ "Euro-House",
/*126*/ "Dance Hall",
/*127*/ "Goa",
/*128*/ "Drum & Bass",
/*129*/ "Club-House",
/*130*/ "Hardcore",
/*131*/ "Terror",
/*132*/ "Indie",
/*133*/ "BritPop",
/*134*/ "Negerpunk",
/*135*/ "Polsk Punk",
/*136*/ "Beat",
/*137*/ "Christian Gansta Rap",
/*138*/ "Heavy Metal",
/*139*/ "Black Metal",
/*140*/ "Crossover",
/*141*/ "Contemporary Christian",
/*142*/ "Christian Rock",
/*143*/ "Merengue",
/*144*/ "Salsa",
/*145*/ "Thrash Metal",
/*146*/ "Anime",
/*147*/ "Jpop",
/*148*/ "Synthpop"
};
#endif
/* the id3v2.2 library.
* (c)2002 by Samuel Abels (sam@manicsadness.com) and Warren Dukes
* This project's homepage is: http://software.manicsadness.com/cantus
*
* This library is designed for easyest possible access to id3 V2 tags.
*
* 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 DLL_H
#define DLL_H
typedef struct DLL_s
{
void *prev;
void *data;
void *next;
} DLL;
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef id3Tag_def
#define id3Tag_def
typedef struct id3Tag_s
{
char title[1024];
char artist[1024];
char album[1024];
char year[5];
char comment[1024];
char track[10];
char genre[512];
unsigned int size;
short int has_footer;
} id3Tag;
typedef struct id3v22Tag_s
{
// header
int tag_size;
short int unsync;
short int is_experimental;
//extheader
int padding_size;
short int crc_data_present;
char crc_data[4];
// frames
DLL *frames;
} id3v22Tag;
typedef struct id3v22Frame_s
{
unsigned char id[3];
int datasize;
short int tagalter;
short int filealter;
short int readonly;
short int compression;
short int encryption;
short int grouping;
char *data;
} id3v22Frame;
#endif
extern int get_id3v22_tag(id3Tag *tag, char *filename);
extern int set_id3v22_tag(id3Tag *tag, char *filename);
extern int del_id3v22_tag(char *filename);
/* the id3v2.3 library.
* (c)2002 by Samuel Abels (sam@manicsadness.com)
* This project's homepage is: http://software.manicsadness.com/cantus
*
* This library is designed for easyest possible access to id3 V2 tags.
*
* 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 DLL_H
#define DLL_H
typedef struct DLL_s
{
void *prev;
void *data;
void *next;
} DLL;
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef id3Tag_def
#define id3Tag_def
typedef struct id3Tag_s
{
char title[1024];
char artist[1024];
char album[1024];
char year[5];
char comment[1024];
char track[10];
char genre[512];
unsigned int size;
short int has_footer;
} id3Tag;
typedef struct id3v2Tag_s
{
// header
int tag_size;
short int unsync;
short int has_extheader;
short int is_experimental;
//extheader
int extheader_size;
int padding_size;
short int crc_data_present;
char crc_data[4];
// frames
DLL *frames;
} id3v2Tag;
typedef struct id3v2Frame_s
{
unsigned char id[4];
int datasize;
short int tagalter;
short int filealter;
short int readonly;
short int compression;
short int encryption;
short int grouping;
char *data;
} id3v2Frame;
#endif
extern int get_id3v2_tag(id3Tag *tag, char *filename);
extern int set_id3v2_tag(id3Tag *tag, char *filename);
extern int del_id3v2_tag(char *filename);
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "info.h"
#include "command.h"
#include "tag.h"
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
int info(FILE * fp, char * file) {
MpdTag * tag;
struct stat st;
if(stat(file,&st)) {
fprintf(fp,"%s not able to stat file\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(!S_ISREG(st.st_mode)) {
fprintf(fp,"%s not a file\n",COMMAND_RESPOND_ERROR);
return -1;
}
if((tag=id3Dup(file))) {
printMpdTag(fp,tag);
freeMpdTag(tag);
return 0;
}
fprintf(fp,"%s problems geting id3 info\n",COMMAND_RESPOND_ERROR);
return -1;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 INFO_H
#define INFO_H
#include <stdio.h>
int info(FILE * fp, char * file);
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "interface.h"
#include "buffer2array.h"
#include "command.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#define VERSION "0.5.2"
#define GREETING "MPD"
#define INTERFACE_MAX_BUFFER_LENGTH 1024
#define INTERFACE_MAX_CONNECTIONS 5
#define INTERFACE_TIMEOUT 60
typedef struct _Interface {
char buffer[INTERFACE_MAX_BUFFER_LENGTH+1];
int bufferLength;
int fd; /* file descriptor */
FILE * fp; /* file pointer */
int open; /* open/used */
time_t lastTime;
} Interface;
Interface interfaces[INTERFACE_MAX_CONNECTIONS];
void openInterface(Interface * interface, int fd) {
assert(interface->open==0);
interface->bufferLength = 0;
interface->fd = fd;
interface->fp = fdopen(fd,"w");
interface->open = 1;
interface->lastTime = time(NULL);
fprintf(interface->fp,"%s %s %s\n",COMMAND_RESPOND_OK,GREETING,VERSION);
}
void closeInterface(Interface * interface) {
assert(interface->open);
interface->open = 0;
if(fclose(interface->fp)) {
fprintf(stderr,"Error closing file pointer\n");
}
}
void openAInterface(int fd) {
int i;
for(i=0;i<INTERFACE_MAX_CONNECTIONS && interfaces[i].open;i++);
if(i==INTERFACE_MAX_CONNECTIONS) {
FILE * fp = fdopen(fd,"w");
fprintf(fp,"%s Max Connections Reached!\n",COMMAND_RESPOND_ERROR);
fclose(fp);
close(fd);
}
else {
openInterface(&(interfaces[i]),fd);
}
}
int interfaceReadInput(Interface * interface) {
if(read(interface->fd,interface->buffer+interface->bufferLength,1)) {
int ret = 1;
if(interface->buffer[interface->bufferLength]!='\r') {
interface->bufferLength++;
}
if(interface->bufferLength>=INTERFACE_MAX_BUFFER_LENGTH) {
fprintf(stdout,"Buffer Overflow\n");
closeInterface(interface);
}
if(interface->buffer[interface->bufferLength-1]=='\n') {
int i;
char ** argArray;
int argArrayLength;
interface->buffer[interface->bufferLength-1] = '\0';
argArrayLength = buffer2array(interface->buffer,&argArray);
ret = processCommand(interface->fp,argArrayLength,argArray);
for(i=0;i<argArrayLength;i++) {
free(argArray[i]);
}
free(argArray);
interface->bufferLength = 0;
}
if(ret==0) {
fprintf(interface->fp,"%s\n",COMMAND_RESPOND_OK);
}
if(ret==COMMAND_RETURN_CLOSE) {
closeInterface(interface);
}
return ret;
}
else {
closeInterface(interface);
}
return 1;
}
void addInterfacesToFdSet(fd_set * fds) {
int i;
FD_ZERO(fds);
for(i=0;i<INTERFACE_MAX_CONNECTIONS;i++) {
if(interfaces[i].open) {
FD_SET(interfaces[i].fd,fds);
}
}
}
int readInputFromInterfaces() {
fd_set fds;
struct timeval tv;
int i;
tv.tv_sec = 0;
tv.tv_usec = 0;
addInterfacesToFdSet(&fds);
while(select(FD_SETSIZE,&fds,NULL,NULL,&tv)) {
for(i=0;i<INTERFACE_MAX_CONNECTIONS;i++) {
if(interfaces[i].open && FD_ISSET(interfaces[i].fd,&fds)) {
if(COMMAND_RETURN_KILL==interfaceReadInput(&(interfaces[i]))) {
return COMMAND_RETURN_KILL;
}
interfaces[i].lastTime = time(NULL);
}
}
addInterfacesToFdSet(&fds);
}
return 1;
}
void initInterfaces() {
int i;
for(i=0;i<INTERFACE_MAX_CONNECTIONS;i++) {
interfaces[i].open = 0;
}
}
void closeAllInterfaces() {
int i;
for(i=0;i<INTERFACE_MAX_CONNECTIONS;i++) {
if(interfaces[i].open) {
closeInterface(&(interfaces[i]));
}
}
}
void closeOldInterfaces() {
int i;
for(i=0;i<INTERFACE_MAX_CONNECTIONS;i++) {
if(interfaces[i].open && (time(NULL)-interfaces[i].lastTime>INTERFACE_TIMEOUT)) {
closeInterface(&(interfaces[i]));
}
}
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 INTERFACE_H
#define INTERFACE_H
#include <stdio.h>
#include <time.h>
void initInterfaces();
void openAInterface(int fd);
void closeAllInterfaces();
void closeOldInterfaces();
int readInputFromInterfaces();
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "list.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
List * makeList(ListFreeDataFunc * freeDataFunc) {
List * list = malloc(sizeof(List));
assert(list!=NULL);
list->firstNode = NULL;
list->lastNode = NULL;
list->freeDataFunc = freeDataFunc;
list->numberOfNodes = 0;
return list;
}
int insertInList(List * list,char * key,void * data) {
ListNode * node;
assert(list!=NULL);
assert(key!=NULL);
assert(data!=NULL);
node = malloc(sizeof(ListNode));
assert(node!=NULL);
if(list->firstNode==NULL) {
assert(list->lastNode==NULL);
list->firstNode = node;
}
else {
assert(list->lastNode!=NULL);
assert(list->lastNode->nextNode==NULL);
list->lastNode->nextNode = node;
}
node->key = malloc((strlen(key)+1)*sizeof(char));
assert(node->key!=NULL);
strcpy(node->key,key);
node->data = data;
node->nextNode = NULL;
node->prevNode = list->lastNode;
list->lastNode = node;
list->numberOfNodes++;
return 1;
}
int insertInListWithoutKey(List * list, void * data) {
ListNode * node;
assert(list!=NULL);
assert(data!=NULL);
node = malloc(sizeof(ListNode));
assert(node!=NULL);
if(list->firstNode==NULL) {
assert(list->lastNode==NULL);
list->firstNode = node;
}
else {
assert(list->lastNode!=NULL);
assert(list->lastNode->nextNode==NULL);
list->lastNode->nextNode = node;
}
node->key = NULL;
node->data = data;
node->nextNode = NULL;
node->prevNode = list->lastNode;
list->lastNode = node;
list->numberOfNodes++;
return 1;
}
int findInList(List * list,char * key,void ** data) {
ListNode * tmpNode;
assert(list!=NULL);
tmpNode = list->firstNode;
while(tmpNode!=NULL && strcmp(tmpNode->key,key)!=0) {
tmpNode = tmpNode->nextNode;
}
if(tmpNode!=NULL) {
(*data) = tmpNode->data;
}
else {
return 0;
}
return 1;
}
int deleteFromList(List * list,char * key) {
ListNode * tmpNode;
assert(list!=NULL);
tmpNode = list->firstNode;
while(tmpNode!=NULL && strcmp(tmpNode->key,key)!=0) {
tmpNode = tmpNode->nextNode;
}
if(tmpNode!=NULL)
deleteNodeFromList(list,tmpNode);
else
return 0;
return 1;
}
void deleteNodeFromList(List * list,ListNode * node) {
assert(list!=NULL);
assert(node!=NULL);
if(node->prevNode==NULL) {
list->firstNode = node->nextNode;
}
else {
node->prevNode->nextNode = node->nextNode;
}
if(node->nextNode==NULL) {
list->lastNode = node->prevNode;
}
else {
node->nextNode->prevNode = node->prevNode;
}
if(list->freeDataFunc) {
list->freeDataFunc(node->data);
}
free(node->key);
free(node);
list->numberOfNodes--;
}
void freeList(void * list) {
ListNode * tmpNode;
ListNode * tmpNode2;
assert(list!=NULL);
tmpNode = ((List *)list)->firstNode;
while(tmpNode!=NULL) {
tmpNode2 = tmpNode->nextNode;
free(tmpNode->key);
if(((List *)list)->freeDataFunc) {
((List *)list)->freeDataFunc(tmpNode->data);
}
free(tmpNode);
tmpNode = tmpNode2;
}
free(list);
}
void clearList(List * list) {
ListNode * tmpNode;
ListNode * tmpNode2;
assert(list!=NULL);
tmpNode = ((List *)list)->firstNode;
while(tmpNode!=NULL) {
tmpNode2 = tmpNode->nextNode;
free(tmpNode->key);
if(((List *)list)->freeDataFunc) {
((List *)list)->freeDataFunc(tmpNode->data);
}
free(tmpNode);
tmpNode = tmpNode2;
}
list->firstNode = NULL;
list->lastNode = NULL;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 LIST_H
#define LIST_H
#include <stdlib.h>
/* used to make a list where free() will be used to free data in list */
#define DEFAULT_FREE_DATA_FUNC free
/* typedef for function to free data stored in the list nodes */
typedef void ListFreeDataFunc(void *);
typedef struct _ListNode {
/* used to identify node (ie. when using findInList) */
char * key;
/* data store in node */
void * data;
/* next node in list */
struct _ListNode * nextNode;
/* previous node in list */
struct _ListNode * prevNode;
} ListNode;
typedef struct _List {
/* first node in list */
ListNode * firstNode;
/* last node in list */
ListNode * lastNode;
/* function used to free data stored in nodes of the list */
ListFreeDataFunc * freeDataFunc;
/* number of ndoes */
int numberOfNodes;
} List;
/* allocates memmory for a new list and initializes it
* _freeDataFunc_ -> pointer to function used to free data, use
* DEFAULT_FREE_DATAFUNC to use free()
* returns pointer to new list if successful, NULL otherwise
*/
List * makeList(ListFreeDataFunc * freeDataFunc);
/* inserts a node into _list_ with _key_ and _data_
* _list_ -> list the data will be inserted in
* _key_ -> identifier for node/data to be inserted into list
* _data_ -> data to be inserted in list
* returns 1 if successful, 0 otherwise
*/
int insertInList(List * list,char * key,void * data);
int insertInListWithoutKey(List * list,void * data);
/* deletes the first node in the list with the key _key_
* _list_ -> list the node will be deleted from
* _key_ -> key used to identify node to delete
* returns 1 if node is found and deleted, 0 otherwise
*/
int deleteFromList(List * list,char * key);
void deleteNodeFromList(List * list,ListNode * node);
/* finds data in a list based on key
* _list_ -> list to search for _key_ in
* _key_ -> which node is being searched for
* _data_ -> a pointer to where data will be placed,
* _data_ memmory should not by allocated or freed
* returns 1 if successful, 0 otherwise
*/
int findInList(List * list, char * key, void ** data);
/* frees memmory malloc'd for list and its nodes
* _list_ -> List to be free'd
*/
void freeList(void * list);
void clearList(List * list);
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "ls.h"
#include "command.h"
#include "playlist.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int ls(FILE * fp, char * dirname) {
DIR * dir;
char cwd[2];
char c;
struct stat st;
struct dirent * ent;
char s[MAXPATHLEN];
cwd[0] = '.';
cwd[1] = '\0';
if(dirname==NULL) dirname=cwd;
if((dir = opendir(dirname))==NULL) {
fprintf(fp,"%s problems opening directory\n",COMMAND_RESPOND_ERROR);
return -1;
}
while((ent = readdir(dir))) {
if(ent->d_name[0]=='.') continue; /* hide hidden stuff */
sprintf(s,"%s/%s",dirname,ent->d_name);
if(stat(s,&st)==0) {
c = 0;
if(S_ISDIR(st.st_mode)) c = 'd';
else if(isMp3(s)) c = 'm';
if(c && dirname==cwd) {
fprintf(fp,"%c \"%s\"\n",c,ent->d_name);
}
else if(c) {
fprintf(fp,"%c \"%s/%s\"\n",c,dirname,ent->d_name);
}
}
}
closedir(dir);
return 0;
}
int lsPlaylists(FILE * fp) {
DIR * dir;
struct stat st;
struct dirent * ent;
char * cLast;
char * cNext;
char * dup;
char s[MAXPATHLEN];
if((dir = opendir(playlistDir))==NULL) {
fprintf(fp,"%s problems opening playlist directory\n",COMMAND_RESPOND_ERROR);
return -1;
}
while((ent = readdir(dir))) {
if(ent->d_name[0]=='.') continue; /* hide hidden stuff */
sprintf(s,"%s/%s",playlistDir,ent->d_name);
if(stat(s,&st)==0) {
if(S_ISREG(st.st_mode)) {
dup = strdup(ent->d_name);
cNext = cLast = strtok(dup,".");
while((cNext = strtok(NULL,"."))) cLast = cNext;
if(cLast && 0==strcmp(cLast,PLAYLIST_FILE_SUFFIX)) {
strncpy(dup,ent->d_name,strlen(ent->d_name)-strlen(PLAYLIST_FILE_SUFFIX)-1);
fprintf(fp,"playlist: %s\n",dup);
}
free(dup);
}
}
}
closedir(dir);
return 0;
}
time_t isMp3(char * file) {
struct stat st;
if(stat(file,&st)==0) {
if(S_ISREG(st.st_mode)) {
char * dup;
char * cLast;
char * cNext;
int ret = 0;
dup = strdup(file);
cNext = cLast = strtok(dup,".");
while((cNext = strtok(NULL,"."))) cLast = cNext;
if(cLast && 0==strcasecmp(cLast,"mp3")) {
ret = st.st_mtime;
}
free(dup);
return ret;
}
else return 0;
}
return 0;
}
time_t isDir(char * name) {
struct stat st;
if(stat(name,&st)==0) {
if(S_ISDIR(st.st_mode)) return st.st_mtime;
}
return 0;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 LS_H
#define LS_H
#include <stdio.h>
#include <time.h>
#include "id3v2lib/lib_id3v2.3.h"
int ls(FILE * fp, char * dir);
int lsPlaylists(FILE * fp);
time_t isMp3(char * file);
time_t isDir(char * name);
#endif
/* the Music Player Daemon (MPD)
* (c)2002 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://musicpd.sourceforge.net
*
* This library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "interface.h"
#include "command.h"
#include "mpg123.h"
#include "playlist.h"
#include "directory.h"
#include "tables.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#define MAXHOSTNAME 1024
void usage(char * argv[]) {
fprintf(stderr,"usage: %s <port> <mp3 dir> <playlist dir> <log file> <error file>\n",argv[0]);
}
int establish(unsigned short port) {
char myname[MAXHOSTNAME+1];
int sock;
struct sockaddr_in sockAddr;
struct hostent * he;
memset(&sockAddr, 0, sizeof(struct sockaddr_in));
gethostname(myname,MAXHOSTNAME);
he = gethostbyname(myname);
if(he == NULL) {
fprintf(stderr,"he == NULL\n");
return -1;
}
sockAddr.sin_family = he->h_addrtype;
sockAddr.sin_port = htons(port);
if((sock = socket(AF_INET,SOCK_STREAM,0)) < 0) {
fprintf(stderr,"socket < 0\n");
return -1;
}
if(bind(sock,(struct sockaddr *)&sockAddr,sizeof(struct sockaddr_in)) < 0) {
fprintf(stderr,"bind < 0\n");
close(sock);
return -1;
}
listen(sock,0);
return sock;
}
void getConnections(int sock) {
fd_set fdsr;
int fd;
struct timeval tv;
tv.tv_sec = tv.tv_usec = 0;
fflush(NULL);
FD_ZERO(&fdsr);
FD_SET(sock,&fdsr);
if(select(sock+1,&fdsr,NULL,NULL,&tv)==1 &&
((fd = accept(sock,NULL,NULL)) >= 0)) {
openAInterface(fd);
}
else if(fd<0) {
fprintf(stderr,"Problems accept()'ing\n");
}
}
int main(int argc, char * argv[]) {
int port;
int sock;
struct stat st;
FILE * out;
FILE * err;
if(argc!=6) {
usage(argv);
return -1;
}
if((port = atoi(argv[1]))<0) {
fprintf(stderr,"problem with port number\n");
return -1;
}
if(NULL==(out=fopen(argv[4],"a"))) {
fprintf(stderr,"problem opening file \"%s\" for writing\n",argv[3]);
return -1;
}
if(NULL==(err=fopen(argv[5],"a"))) {
fprintf(stderr,"problem opening file \"%s\" for writing\n",argv[3]);
return -1;
}
if((stat(argv[2],&st))<0) {
fprintf(stderr,"problem stat'ing \"%s\"\n",argv[2]);
return -1;
}
if(!S_ISDIR(st.st_mode)) {
fprintf(stderr,"\"%s\" is not a directory\n",argv[2]);
return -1;
}
if(argv[3][0]=='/') {
strcpy(playlistDir,argv[3]);
}
else {
getcwd(playlistDir,MAXPATHLEN-strlen(argv[3])-1);
strcat(playlistDir,"/");
strcat(playlistDir,argv[3]);
strcat(playlistDir,"/");
}
if((stat(playlistDir,&st))<0) {
fprintf(stderr,"problem stat'ing \"%s\"\n",argv[3]);
return -1;
}
if(!S_ISDIR(st.st_mode)) {
fprintf(stderr,"\"%s\" is not a directory\n",argv[3]);
return -1;
}
chdir(argv[2]);
initTables();
strcpy(directorydb,playlistDir);
strcat(directorydb,"/");
strcat(directorydb,".mpddb");
if(readDirectoryDB()<0) {
initMp3Directory();
if(writeDirectoryDB()<0) {
fprintf(stderr,"problem opening db for reading or writing\n");
exit(-1);
}
}
if((sock = establish(port))<0) {
fprintf(stderr,"error bindping port\n");
return -1;
}
initInterfaces();
initPlaylist();
daemon(1,0);
dup2(fileno(out),STDOUT_FILENO);
dup2(fileno(err),STDERR_FILENO);
while(COMMAND_RETURN_KILL!=readInputFromInterfaces()) {
mpg123processMessages();
getConnections(sock);
closeOldInterfaces();
usleep(1000);
}
clearPlaylist(stderr);
closeAllInterfaces();
close(sock);
mpg123stop(stderr);
mpg123kill();
closeTables();
closeMp3Directory();
return 0;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "mpg123.h"
#include "command.h"
#include "interface.h"
#include "playlist.h"
#include "ls.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>
#define MAX_BUFFER_LENGTH 1024
#define MPG123_PLAYER_BUFFER_SIZE "2048"
int mpg123_pid = 0;
int mpg123_send = 0;
int mpg123_recv = 0;
int mpg123_stderr = 0;
char mpg123_buffer[MAX_BUFFER_LENGTH+1];
int mpg123_bufferLength = 0;
int mpg123_totalTime = 0;
int mpg123_elapsedTime = 0;
int mpg123_reportedElapsedTime = 0;
int mpg123_state = MPG123_STATE_STOP;
int mpg123_leavePlay = 0;
int mpg123_leavePause = 0;
int mpg123_error = 0;
int mpg123_stopAtEnd = 0;
int mpg123_lastFrame = 0;
void mpg123_sigHandler(int signal) {
if(signal==SIGCHLD) {
wait3(NULL,WNOHANG,NULL);
mpg123_pid = 0;
close(mpg123_recv);
close(mpg123_send);
close(mpg123_stderr);
if(mpg123_state==MPG123_STATE_PLAY) {
mpg123_leavePlay = 1;
fprintf(stderr,"mpg123 died while playing\n");
nextSongInPlaylist(stderr);
}
mpg123_state = MPG123_STATE_STOP;
}
}
int mpg123init() {
int fd_send[2], fd_recv[2], fd_stderr[2];
mpg123_error = 0;
mpg123_stopAtEnd = 0;
if(socketpair(AF_UNIX,SOCK_STREAM,0,fd_send)<0) {
fprintf(stderr,"%s Problems socketpair'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(socketpair(AF_UNIX,SOCK_STREAM,0,fd_recv)<0) {
fprintf(stderr,"%s Problems socketpair()'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(socketpair(AF_UNIX,SOCK_STREAM,0,fd_stderr)<0) {
fprintf(stderr,"%s Problems socketpair()'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
signal(SIGPIPE,SIG_IGN);
signal(SIGCHLD,mpg123_sigHandler);
mpg123_pid = fork();
if(mpg123_pid==0) {
closeAllInterfaces();
close(fd_send[0]);
close(fd_recv[0]);
close(fd_stderr[0]);
dup2(fd_send[1],STDIN_FILENO);
close(fd_send[1]);
dup2(fd_recv[1],STDOUT_FILENO);
close(fd_recv[1]);
dup2(fd_stderr[1],STDERR_FILENO);
close(fd_stderr[1]);
if(execlp("mpg123","mpg123","-b",MPG123_PLAYER_BUFFER_SIZE,"-R","foo",NULL)<0) {
fprintf(stderr,"%s Problems spawning mpg123\n",COMMAND_RESPOND_ERROR);
return -1;
}
}
else if(mpg123_pid<0) {
fprintf(stderr,"%s Problems fork()'ing\n",COMMAND_RESPOND_ERROR);
mpg123_pid = 0;
close(fd_send[0]);
close(fd_send[1]);
close(fd_recv[0]);
close(fd_recv[1]);
close(fd_stderr[0]);
close(fd_stderr[1]);
return -1;
}
close(fd_send[1]);
close(fd_recv[1]);
close(fd_stderr[1]);
mpg123_send = fd_send[0];
mpg123_recv = fd_recv[0];
mpg123_stderr = fd_stderr[0];
return 0;
}
int mpg123play(FILE * fp, char * file) {
char string[1024];
mpg123_leavePlay = 0;
if(fp==NULL) fp=stderr;
if(!isMp3(file)) {
fprintf(fp,"%s \"%s\" is not a mp3\n",file,COMMAND_RESPOND_ERROR);
return -1;
}
if(!mpg123_pid) {
if(mpg123init()<0) return -1;
}
sprintf(string,"LOAD %s\n",file);
if(write(mpg123_send,string,strlen(string))<0) {
fprintf(fp,"%s problems write'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
mpg123_state = MPG123_STATE_PLAY;
/*sleep until status is updated*/
while(!mpg123_leavePlay) {
mpg123processMessages();
usleep(1000);
}
if(mpg123_error) {
fprintf(fp,"%s problems playing \"%s\"\n",COMMAND_RESPOND_ERROR,file);
/*nextSongInPlaylist(stderr);*/
mpg123kill();
return -1;
}
return 0;
}
int mpg123stop(FILE * fp) {
if(mpg123_pid>0) {
char string[1024];
if(mpg123_state==MPG123_STATE_PAUSE) {
if(mpg123pause(fp)<0) return -1;
}
mpg123_state = MPG123_STATE_STOP;
sprintf(string,"QUIT\n");
if(write(mpg123_send,string,strlen(string))<0) {
fprintf(fp,"%s problems write'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
wait3(NULL,WUNTRACED,NULL);
if(mpg123_pid>0) {
fprintf(fp,"oh shit\n");
mpg123kill();
}
}
mpg123_state = MPG123_STATE_STOP;
return 0;
}
int mpg123pause(FILE * fp) {
char string[1024];
if(mpg123_pid>0) {
sprintf(string,"PAUSE\n");
if(write(mpg123_send,string,strlen(string))<0) {
fprintf(fp,"%s problems write'ing\n",COMMAND_RESPOND_ERROR);
}
mpg123_leavePause = 0;
while(!mpg123_leavePause) {
mpg123processMessages();
usleep(1000);
}
if(mpg123_state==MPG123_STATE_PLAY) {
mpg123_state = MPG123_STATE_PAUSE;
}
else if(mpg123_state==MPG123_STATE_PAUSE) {
mpg123_state = MPG123_STATE_PLAY;
}
}
return 0;
}
int mpg123readline() {
fd_set fdsr;
struct timeval tv;
FD_ZERO(&fdsr);
FD_SET(mpg123_recv,&fdsr);
tv.tv_sec = tv.tv_usec = 0;
if(select(mpg123_recv+1,&fdsr,NULL,NULL,&tv)==1) {
int rc;
while(1) {
rc = read(mpg123_recv,mpg123_buffer+mpg123_bufferLength,1);
if(rc<=0) {
/*mpg123_pid = 0;
mpg123_state = MPG123_STATE_STOP;*/
return -1;
}
if(mpg123_buffer[mpg123_bufferLength]=='\0' || mpg123_buffer[mpg123_bufferLength]=='\n' || mpg123_bufferLength == MAX_BUFFER_LENGTH) {
mpg123_buffer[mpg123_bufferLength] = '\0';
mpg123_bufferLength = 0;
return -1;
}
mpg123_bufferLength++;
}
}
return 0;
}
int mpg123gotErrors() {
int ret = 0;
fd_set fdsr;
struct timeval tv;
FD_ZERO(&fdsr);
FD_SET(mpg123_stderr,&fdsr);
tv.tv_sec = tv.tv_usec = 0;
if(select(mpg123_stderr+1,&fdsr,NULL,NULL,&tv)==1) {
int rc;
char errorBuffer[MAX_BUFFER_LENGTH];
int errorBufferLength = 0;
while(1) {
rc = read(mpg123_stderr,errorBuffer+errorBufferLength,1);
if(rc<=0) {
return 0;
}
if(errorBuffer[errorBufferLength]=='\0' || errorBuffer[errorBufferLength]=='\n' || errorBufferLength == MAX_BUFFER_LENGTH) {
errorBuffer[errorBufferLength] = '\0';
errorBufferLength = 0;
if(!strncmp("Junk",errorBuffer,strlen("Junk"))) {
return 0;
}
fprintf(stderr,"%s %s\n",COMMAND_RESPOND_ERROR,errorBuffer);
mpg123kill();
return 1;
}
errorBufferLength++;
}
}
return ret;
}
int mpg123processMessages() {
if(mpg123_pid>0) {
while(mpg123readline()) {
char * c[6];
int i;
c[0] = strtok(mpg123_buffer," \t");
if(c[0]) {
for(i=1;i<6;i++) {
c[i] = c[i-1] ? strtok(NULL," \t") : NULL;
}
if(0==strcmp(c[0],"@F")) {
mpg123_totalTime = atof(c[3])+atof(c[4])+0.5;
mpg123_reportedElapsedTime = atof(c[3])+0.5;
if(atof(c[3])<1) mpg123_leavePlay = 1;
mpg123_lastFrame = time(NULL);
if(mpg123_stopAtEnd && atof(c[4])<1) {
mpg123_stopAtEnd = 0;
mpg123stop(stderr);
}
}
else if(0==strcmp(c[0],"@P")) {
if(mpg123_state==MPG123_STATE_PLAY && atoi(c[1])==MPG123_STATE_STOP) {
if(!mpg123_leavePlay) {
mpg123_leavePlay=1;
mpg123_error = 1;
}
else {
nextSongInPlaylist(stderr);
}
}
else if(mpg123_state==MPG123_STATE_PLAY && atoi(c[1])==MPG123_STATE_PAUSE) {
mpg123_leavePause = 1;
}
else if(mpg123_state==MPG123_STATE_PAUSE && atoi(c[1])==MPG123_STATE_PLAY) {
mpg123_leavePause = 1;
}
//mpg123_state = atoi(c[1]);
}
/*else if(0==strcmp(c[0],"@I")) {
mpg123_leavePlay = 1;
}*/
else if(0==strcmp(c[0],"@E")) {
mpg123_error = 1;
}
}
}
if(mpg123gotErrors()) mpg123_error = 1;
if(mpg123_stopAtEnd) {
mpg123_elapsedTime = mpg123_reportedElapsedTime+time(NULL)-mpg123_lastFrame;
}
else {
mpg123_elapsedTime = mpg123_reportedElapsedTime;
}
if(mpg123_stopAtEnd && mpg123_elapsedTime>mpg123_totalTime) {
mpg123_stopAtEnd = 0;
mpg123stop(stderr);
}
}
return 0;
}
void mpg123kill() {
/* new stuff to try */
//kill(-1,SIGKILL);
/* old new stuff to try */
if(mpg123_pid>0) system("killall -KILL mpg123");
mpg123_state = MPG123_STATE_STOP;
mpg123_sigHandler(SIGCHLD);
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 MPG123_H
#define MPG123_H
#include <stdio.h>
#define MPG123_STATE_STOP 0
#define MPG123_STATE_PAUSE 1
#define MPG123_STATE_PLAY 2
#define MPG123_KILL 1
#define MPG123_NOKILL 0
extern int mpg123_totalTime;
extern int mpg123_elapsedTime;
extern int mpg123_state;
extern int mpg123_stopAtEnd;
void mpg123_sigHandler(int signal);
int mpg123play(FILE * fp, char * file);
int mpg123pause(FILE * fp);
int mpg123stop(FILE * fp);
void mpg123kill();
int mpg123processMessages();
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "playlist.h"
#include "mpg123.h"
#include "command.h"
#include "ls.h"
#include "tag.h"
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
Playlist playlist;
char playlistDir[MAXPATHLEN+1];
void initPlaylist() {
playlist.length = 0;
memset(playlist.songs,(int)NULL,sizeof(char *)*PLAYLIST_MAX_LENGTH);
}
int checkThatPlaylistIsStopped(FILE * fp) {
if(mpg123_state!=MPG123_STATE_STOP) {
fprintf(fp,"%s playlist is not stopped\n",COMMAND_RESPOND_ERROR);
return -1;
}
return 0;
}
int clearPlaylist(FILE * fp) {
int i;
if(mpg123stop(fp)<0) return -1;
for(i=0;i<playlist.length;i++) {
freeSong(playlist.songs[i]);
}
playlist.length = 0;
return 0;
}
int addToPlaylist(FILE * fp, char * file) {
if(!isMp3(file)) {
fprintf(fp,"%s \"%s\" is not a mp3\n",COMMAND_RESPOND_ERROR,file);
return -1;
}
if(playlist.length==PLAYLIST_MAX_LENGTH) {
fprintf(fp,"%s playlist is at the max size\n",COMMAND_RESPOND_ERROR);
return -1;
}
playlist.songs[playlist.length] = newSong(file);
playlist.length++;
return 0;
}
int showPlaylist(FILE * fp) {
int i;
for(i=0;i<playlist.length;i++) {
fprintf(fp,"%i \"%s\"\n",i,(playlist.songs[i])->file);
}
return 0;
}
int playlistInfo(FILE * fp,int song) {
MpdTag * tag;
int i;
int begin = 0;
int end = playlist.length;
if(song>=0) {
begin = song;
end = song+1;
}
if(song>=playlist.length) {
fprintf(fp,"%s song doesn't exist\n",COMMAND_RESPOND_ERROR);
return -1;
}
for(i=begin;i<end;i++) {
fprintf(fp,"file: %s\n",(playlist.songs[i])->file);
if((tag = (playlist.songs[i])->tag)) {
printMpdTag(fp,tag);
}
}
return 0;
}
void swapSongs(int song1, int song2) {
Song * temp;
temp = playlist.songs[song1];
playlist.songs[song1] = playlist.songs[song2];
playlist.songs[song2] = temp;
}
int deleteFromPlaylist(FILE * fp, int song) {
int i;
if(song<0) {
fprintf(fp,"%s need a positive interger\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(song>=playlist.length) {
fprintf(fp,"%s song doesn't exist\n",COMMAND_RESPOND_ERROR);
return -1;
}
freeSong(playlist.songs[song]);
playlist.songs[song] = NULL;
for(i=song;i<playlist.length-1;i++) swapSongs(i,i+1);
playlist.length--;
if(mpg123_state!=MPG123_STATE_STOP && playlist.current==song) {
if(playlist.current>=playlist.length) return mpg123stop(fp);
else return playPlaylist(fp,playlist.current);
}
else if(mpg123_state!=MPG123_STATE_STOP && playlist.current>song) {
playlist.current--;
}
return 0;
}
int playPlaylist(FILE * fp, int song) {
if(song<0) {
fprintf(fp,"%s need a positive interger\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(song>=playlist.length) {
fprintf(fp,"%s song doesn't exist\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(mpg123stop(fp)<0) return -1;
playlist.current = song;
return mpg123play(fp,(playlist.songs[song])->file);
}
int nextSongInPlaylist(FILE * fp) {
while(playlist.current<playlist.length-1) {
playlist.current++;
if(mpg123play(fp,(playlist.songs[playlist.current])->file)==0) return 0;
}
if(playlist.current==playlist.length-1) {
mpg123_stopAtEnd = 1;
}
else {
mpg123stop(fp); /*stop and kill mpg123*/
}
return 0;
}
int shufflePlaylist(FILE * fp) {
int i;
int ri;
srand(time(NULL));
for(i=0;i<playlist.length;i++) {
ri = rand()%playlist.length;
swapSongs(i,ri);
if(i==playlist.current) playlist.current=ri;
else if(ri==playlist.current) playlist.current=i;
}
return 0;
}
int deletePlaylist(FILE * fp, char * file) {
struct stat st;
if(stat(file,&st)<0) {
fprintf(fp,"%s problems stat'ing\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(!S_ISREG(st.st_mode)) {
fprintf(fp,"%s not a file\n",COMMAND_RESPOND_ERROR);
return -1;
}
if(unlink(file)<0) {
fprintf(fp,"%s problems deleting file\n",COMMAND_RESPOND_ERROR);
return -1;
}
return 0;
}
int savePlaylist(FILE * fp, char * file) {
FILE * fileP;
int i;
struct stat st;
if(0==stat(file,&st)) {
fprintf(fp,"%s A file or direcory already exists with the name \"%s\"\n",COMMAND_RESPOND_ERROR,file);
return -1;
}
if((fileP = fopen(file,"w"))==NULL) {
fprintf(fp,"%s Problems opening file\n",COMMAND_RESPOND_ERROR);
return -1;
}
for(i=0;i<playlist.length;i++) {
fprintf(fileP,"%s\n",(playlist.songs[i])->file);
}
fclose(fileP);
return 0;
}
int loadPlaylist(FILE * fp, char * file) {
FILE * fileP;
char s[MAXPATHLEN+1];
int slength = 0;
if((fileP = fopen(file,"r"))==NULL) {
fprintf(fp,"%s Problems opening file\n",COMMAND_RESPOND_ERROR);
return -1;
}
while((s[slength] = fgetc(fileP))!=EOF) {
if(s[slength]=='\n') {
s[slength] = '\0';
if((addToPlaylist(fp,s))<0) return -1;
slength = 0;
}
else if(slength==MAXPATHLEN) {
s[slength] = '\0';
fprintf(fp,"%s \"%s\" too long\n",COMMAND_RESPOND_ERROR,s);
return -1;
}
else {
slength++;
}
}
fclose(fileP);
return 0;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 PLAYLIST_H
#define PLAYLIST_H
#include "song.h"
#include <stdio.h>
#include <sys/param.h>
#define PLAYLIST_FILE_SUFFIX "m3u"
#define PLAYLIST_MAX_LENGTH 1024
extern char playlistDir[MAXPATHLEN+1];
typedef struct _Playlist {
Song * songs[PLAYLIST_MAX_LENGTH];
int length;
int current;
} Playlist;
void initPlaylist();
int clearPlaylist(FILE * fp);
int addToPlaylist(FILE * fp, char * file);
int showPlaylist(FILE * fp);
int deleteFromPlaylist(FILE * fp, int song);
int playlistInfo(FILE * fp, int song);
int playPlaylist(FILE * fp, int song);
int nextSongInPlaylist(FILE * fp);
int shufflePlaylist(FILE * fp);
int savePlaylist(FILE * fp, char * file);
int deletePlaylist(FILE * fp, char * file);
int loadPlaylist(FILE * fp, char * file);
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "song.h"
#include "ls.h"
#include "directory.h"
#include "tables.h"
#include "utils.h"
#include "tag.h"
#define SONG_KEY "key: "
#define SONG_FILE "file: "
#define SONG_ARTIST "Artist: "
#define SONG_ALBUM "Album: "
#define SONG_TRACK "Track: "
#define SONG_TITLE "Title: "
#define SONG_MTIME "mtime: "
#include <stdlib.h>
#include <string.h>
Song * newSong(char * file) {
Song * song = malloc(sizeof(Song));
song->file = strdup(file);
song->tag = id3Dup(file);
song->mtime = isMp3(file);
return song;
}
void freeSong(Song * song) {
free(song->file);
if(song->tag) freeMpdTag(song->tag);
free(song);
}
SongList * newSongList() {
return makeList((ListFreeDataFunc *)freeSong);
}
Song * addSongToList(SongList * list, char * key, char * file) {
Song * song;
if(isMp3(file)) {
song = newSong(file);
}
else {
return NULL;
}
insertInList(list,key,(void *)song);
return song;
}
void freeSongList(SongList * list) {
freeList(list);
}
int printSongInfo(FILE * fp, Song * song) {
fprintf(fp,"%s%s\n",SONG_FILE,song->file);
if(song->tag) printMpdTag(fp,song->tag);
return 0;
}
int printSongInfoFromList(FILE * fp, SongList * list) {
ListNode * tempNode = list->firstNode;
while(tempNode!=NULL) {
printSongInfo(fp,(Song *)tempNode->data);
tempNode = tempNode->nextNode;
}
return 0;
}
void writeSongInfoFromList(FILE * fp, SongList * list) {
ListNode * tempNode = list->firstNode;
fprintf(fp,"%s\n",SONG_BEGIN);
while(tempNode!=NULL) {
fprintf(fp,"%s%s\n",SONG_KEY,tempNode->key);
printSongInfo(fp,(Song *)tempNode->data);
fprintf(fp,"%s%li\n",SONG_MTIME,((Song *)tempNode->data)->mtime);
tempNode = tempNode->nextNode;
}
fprintf(fp,"%s\n",SONG_END);
}
void readSongInfoIntoList(FILE * fp, SongList * list) {
char buffer[MAXPATHLEN+1024];
int bufferSize = MAXPATHLEN+1024;
Song * song = NULL;
char * key;
while(myFgets(buffer,bufferSize,fp) && 0!=strcmp(SONG_END,buffer)) {
if(0==strncmp(SONG_KEY,buffer,strlen(SONG_KEY))) {
if(song) {
insertInList(list,key,(void *)song);
if(song->tag) addSongToTables(song);
free(key);
}
key = strdup(&(buffer[strlen(SONG_KEY)]));
song = malloc(sizeof(Song));
song->tag = NULL;
song->file = NULL;
}
else if(0==strncmp(SONG_FILE,buffer,strlen(SONG_FILE))) {
if(!song || song->file) {
fprintf(stderr,"Problems reading song info\n");
exit(-1);
}
song->file = strdup(&(buffer[strlen(SONG_FILE)]));
}
else if(0==strncmp(SONG_ARTIST,buffer,strlen(SONG_ARTIST))) {
if(!song->tag) song->tag = newMpdTag();
song->tag->artist = strdup(&(buffer[strlen(SONG_ARTIST)]));
}
else if(0==strncmp(SONG_ALBUM,buffer,strlen(SONG_ALBUM))) {
if(!song->tag) song->tag = newMpdTag();
song->tag->album = strdup(&(buffer[strlen(SONG_ALBUM)]));
}
else if(0==strncmp(SONG_TRACK,buffer,strlen(SONG_TRACK))) {
if(!song->tag) song->tag = newMpdTag();
song->tag->track = strdup(&(buffer[strlen(SONG_TRACK)]));
}
else if(0==strncmp(SONG_TITLE,buffer,strlen(SONG_TITLE))) {
if(!song->tag) song->tag = newMpdTag();
song->tag->title = strdup(&(buffer[strlen(SONG_TITLE)]));
}
else if(0==strncmp(SONG_MTIME,buffer,strlen(SONG_MTIME))) {
song->mtime = atoi(&(buffer[strlen(SONG_TITLE)]));
}
else {
fprintf(stderr,"unknown line in db: %s\n",buffer);
exit(-1);
}
}
if(song) {
insertInList(list,key,(void *)song);
if(song->tag) addSongToTables(song);
free(key);
}
}
int updateSongInfo(Song * song) {
if(song->tag) freeMpdTag(song->tag);
if(!(song->mtime = isMp3(song->file))) return -1;
song->tag = id3Dup(song->file);
return 0;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 SONG_H
#define SONG_H
#define SONG_BEGIN "songList begin"
#define SONG_END "songList end"
#include <sys/param.h>
#include <time.h>
#include "tag.h"
#include "list.h"
typedef struct _Song {
char * file;
MpdTag * tag;
time_t mtime;
} Song;
typedef List SongList;
Song * newSong(char * file);
void freeSong(Song *);
SongList * newSongList();
void freeSongList(SongList * list);
Song * addSongToList(SongList * list, char * key, char * file);
int printSongInfo(FILE * fp, Song * song);
int printSongInfoFromList(FILE * fp, SongList * list);
void writeSongInfoFromList(FILE * fp, SongList * list);
void readSongInfoIntoList(FILE * fp, SongList * list);
int updateSongInfo(Song * song);
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "tables.h"
#include "list.h"
#include "command.h"
#include "utils.h"
#include <string.h>
#define TABLES_ALBUM "album"
#define TABLES_ARTIST "artist"
#define TABLES_TITLE "title"
List * albumTable;
List * artistTable;
List * titleTable;
void initTables() {
albumTable = makeList(freeList);
artistTable = makeList(freeList);
titleTable = makeList(NULL);
}
void closeTables() {
freeList(albumTable);
freeList(artistTable);
freeList(titleTable);
}
void addSongToAlbumTable(Song * song) {
SongList * album;
if(!song->tag) return;
if(!song->tag->title) return;
if(findInList(albumTable,song->tag->album,(void **)&album)) {
insertInList(album,song->file,song);
}
else {
album = makeList(NULL);
insertInList(albumTable,song->tag->album,album);
insertInList(album,song->file,song);
}
}
void addSongToArtistTable(Song * song) {
SongList * artist;
if(!song->tag) return;
if(!song->tag->artist) return;
if(findInList(artistTable,song->tag->artist,(void **)&artist)) {
insertInList(artist,song->file,song);
}
else {
artist = makeList(NULL);
insertInList(artistTable,song->tag->artist,artist);
insertInList(artist,song->file,song);
}
}
void addSongToSongTable(Song * song) {
if(!song->tag) return;
if(!song->tag->title) return;
insertInList(titleTable,song->file,song);
}
void addSongToTables(Song * song) {
addSongToAlbumTable(song);
addSongToArtistTable(song);
addSongToSongTable(song);
}
int findAndPrintSongsInAlbumTable(FILE * fp,char * find) {
SongList * album;
if(!findInList(albumTable,find,(void **)&album)) {
fprintf(fp,"%s album not found\n",COMMAND_RESPOND_ERROR);
return -1;
}
return printSongInfoFromList(fp,album);
}
int findAndPrintSongsInArtistTable(FILE * fp,char * find) {
SongList * artist;
if(!findInList(artistTable,find,(void **)&artist)) {
fprintf(fp,"%s artist not found\n",COMMAND_RESPOND_ERROR);
return -1;
}
return printSongInfoFromList(fp,artist);
}
int findAndPrintSongsInTable(FILE * fp, char * table, char * find) {
if(strcmp(table,TABLES_ALBUM)==0) {
return findAndPrintSongsInAlbumTable(fp,find);
}
else if(strcmp(table,TABLES_ARTIST)==0) {
return findAndPrintSongsInArtistTable(fp,find);
}
fprintf(fp,"%s unkown table\n",COMMAND_RESPOND_ERROR);
return -1;
}
int searchForSongsInAlbumTable(FILE * fp,char * search) {
SongList * album;
ListNode * node = albumTable->firstNode;
int ret = -1;
char * dup;
char * dupSearch = strDupToUpper(search);
while(node) {
dup = strDupToUpper(node->key);
if(strstr(dup,dupSearch)) {
album = (SongList *)node->data;
if(printSongInfoFromList(fp,album)<0) {
free(dup);
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 searchForSongsInArtistTable(FILE * fp,char * search) {
SongList * artist;
ListNode * node = artistTable->firstNode;
int ret = -1;
char * dup;
char * dupSearch = strDupToUpper(search);
while(node) {
dup = strDupToUpper(node->key);
if(strstr(dup,dupSearch)) {
artist = (SongList *)node->data;
if(printSongInfoFromList(fp,artist)<0) {
free(dup);
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 searchForSongsInTitleTable(FILE * fp,char * search) {
Song * song;
ListNode * node = titleTable->firstNode;
int ret = -1;
char * dup;
char * dupSearch = strDupToUpper(search);
if(!song->tag || !song->tag->title) return -1;
while(node) {
song = (Song *)node->data;
dup = strDupToUpper(song->tag->title);
if(strstr(dup,dupSearch)) {
if(printSongInfo(fp,song)<0) {
free(dup);
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);
}
else if(strcmp(table,TABLES_ARTIST)==0) {
return searchForSongsInArtistTable(fp,search);
}
else if(strcmp(table,TABLES_TITLE)==0) {
return searchForSongsInTitleTable(fp,search);
}
fprintf(fp,"%s unkown table\n",COMMAND_RESPOND_ERROR);
return -1;
}
void removeSongFromAlbumTable(Song * song) {
List * album;
if(!song->tag) return;
if(!song->tag->album) return;
if(findInList(albumTable,song->tag->album,(void **)&album)) {
deleteFromList(album,song->file);
if(album->numberOfNodes==0) {
deleteFromList(albumTable,song->tag->album);
}
}
}
void removeSongFromArtistTable(Song * song) {
List * artist;
if(!song->tag) return;
if(!song->tag->artist) return;
if(findInList(artistTable,song->tag->artist,(void **)&artist)) {
deleteFromList(artist,song->file);
if(artist->numberOfNodes==0) {
deleteFromList(artistTable,song->tag->artist);
}
}
}
void removeSongFromTitleTable(Song * song) {
deleteFromList(titleTable,song->file);
}
void removeASongFromTables(Song * song) {
removeSongFromAlbumTable(song);
removeSongFromArtistTable(song);
removeSongFromTitleTable(song);
}
void removeSongsFromTables(SongList * songList) {
ListNode * node = songList->firstNode;
Song * song;
while(node) {
song = (Song *)node->data;
removeASongFromTables(song);
node = node->nextNode;
}
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 TABLES_H
#define TABLES_H
#include "song.h"
#include <stdio.h>
void initTables();
void closeTables();
void addSongToTables(Song * song);
int findAndPrintSongsInTable(FILE * fp, char * table, char * find);
int searchForSongsInTable(FILE * fp, char * table, char * find);
void removeSongsFromTables(SongList * songList);
void removeASongFromTables(Song * song);
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "tag.h"
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include "id3v2lib/lib_id3v2.3.h"
#include "id3v2lib/lib_id3v2.2.h"
#include "id3v1lib/lib_id3v1.h"
id3Tag * stripSpaces(id3Tag * tag) {
int len;
len=strlen(tag->artist);
while(len && tag->artist[len-1]==' ') {
tag->artist[len-1] = '\0';
len--;
}
len=strlen(tag->album);
while(len && tag->album[len-1]==' ') {
tag->album[len-1] = '\0';
len--;
}
len=strlen(tag->title);
while(len && tag->title[len-1]==' ') {
tag->title[len-1] = '\0';
len--;
}
return tag;
}
id3Tag * newId3() {
id3Tag * id3 = malloc(sizeof(id3Tag));
id3->artist[0] = '\0';
id3->album[0] = '\0';
id3->track[0] = '\0';
id3->title[0] = '\0';
return id3;
}
void printMpdTag(FILE * fp, MpdTag * tag) {
if(tag->artist) fprintf(fp,"Artist: %s\n",tag->artist);
if(tag->album) fprintf(fp,"Album: %s\n",tag->album);
if(tag->track) fprintf(fp,"Track: %s\n",tag->track);
if(tag->title) fprintf(fp,"Title: %s\n",tag->title);
}
MpdTag * id3Dup(char * file) {
id3Tag * tag = newId3();
MpdTag * ret;
if(0==get_id3v2_tag(tag,file)) stripSpaces(tag);
else if(0==get_id3v22_tag(tag,file)) stripSpaces(tag);
else if(0==get_id3v1_tag(tag,file)) stripSpaces(tag);
else {
free(tag);
return NULL;
}
ret = newMpdTag();
ret->artist = strdup(tag->artist);
ret->album = strdup(tag->album);
ret->title = strdup(tag->title);
ret->track = strdup(tag->track);
free(tag);
return ret;
}
MpdTag * newMpdTag() {
MpdTag * ret = malloc(sizeof(MpdTag));
ret->album = NULL;
ret->artist = NULL;
ret->title = NULL;
ret->track = NULL;
return ret;
}
void freeMpdTag(MpdTag * tag) {
if(tag->artist) free(tag->artist);
if(tag->album) free(tag->album);
if(tag->title) free(tag->title);
if(tag->track) free(tag->track);
free(tag);
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 TAG_H
#define TAG_H
#include <stdio.h>
typedef struct _MpdTag {
char * artist;
char * album;
char * track;
char * title;
} MpdTag;
MpdTag * newMpdTag();
void freeMpdTag(MpdTag * tag);
MpdTag * id3Dup(char * file);
void printMpdTag(FILE * fp, MpdTag * tag);
#endif
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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
*/
#include "utils.h"
#include <string.h>
#include <ctype.h>
char * myFgets(char * buffer, int bufferSize, FILE * fp) {
char * ret = fgets(buffer,bufferSize,fp);
if(ret && strlen(buffer)>0 && buffer[strlen(buffer)-1]=='\n') {
buffer[strlen(buffer)-1] = '\0';
}
return ret;
}
char * strDupToUpper(char * str) {
char * ret = strdup(str);
int i;
for(i=0;i<strlen(str);i++) ret[i] = toupper((int)ret[i]);
return ret;
}
/* 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 library is designed for easyest possible access to id3 V1 tags.
*
* 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 UTILS_H
#define UTILS_H
#include <stdio.h>
char * myFgets(char * buffer, int bufferSize, FILE * fp);
char * strDupToUpper(char * str);
#endif
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