first time actually listing a file

This commit is contained in:
Ron Pedde 2003-11-04 06:11:00 +00:00
parent 231e37d3b8
commit 1647bacae6
7 changed files with 252 additions and 34 deletions

View File

@ -4,7 +4,8 @@ sbin_PROGRAMS = mt-daapd
mt_daapd_SOURCES = main.c daapd.h rend.c rend.h uici.c uici.h webserver.c \ mt_daapd_SOURCES = main.c daapd.h rend.c rend.h uici.c uici.h webserver.c \
webserver.h configfile.c configfile.h err.c err.h restart.c restart.h \ webserver.h configfile.c configfile.h err.c err.h restart.c restart.h \
daap-proto.c daap-proto.h daap.c daap.h \ daap-proto.c daap-proto.h daap.c daap.h db-memory.c db-memory.h \
mp3-scanner.h mp3-scanner.c \
mdns/mDNS.c mdns/mDNSClientAPI.h mdns/mDNSDebug.h mdns/mDNSPosix.c \ mdns/mDNS.c mdns/mDNSClientAPI.h mdns/mDNSDebug.h mdns/mDNSPosix.c \
mdns/mDNSUNP.c mdns/mDNSUNP.c

View File

@ -23,6 +23,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "db-memory.h"
#include "daap-proto.h" #include "daap-proto.h"
#include "daap.h" #include "daap.h"
#include "err.h" #include "err.h"
@ -210,16 +211,66 @@ DAAP_BLOCK *daap_response_login(void) {
DAAP_BLOCK *daap_response_songlist(void) { DAAP_BLOCK *daap_response_songlist(void) {
DAAP_BLOCK *root; DAAP_BLOCK *root;
int g=1; int g=1;
DAAP_BLOCK *mlcl;
DAAP_BLOCK *mlit;
ENUMHANDLE henum;
MP3FILE *current;
henum=db_enum_begin();
if(!henum)
return NULL;
root=daap_add_empty(NULL,"adbs"); root=daap_add_empty(NULL,"adbs");
if(root) { if(root) {
g = (int)daap_add_int(root,"mstt",200); g = (int)daap_add_int(root,"mstt",200);
g = g && daap_add_char(root,"muty",0); g = g && daap_add_char(root,"muty",0);
g = g && daap_add_int(root,"mtco",0); g = g && daap_add_int(root,"mtco",db_get_song_count());
g = g && daap_add_int(root,"mrco",0); g = g && daap_add_int(root,"mrco",db_get_song_count());
g = g && daap_add_empty(root,"mlcl");
mlcl=daap_add_empty(root,"mlcl");
if(mlcl) {
while(current=db_enum(&henum)) {
DPRINTF(ERR_DEBUG,"Got entry for %s\n",current->fname);
mlit=daap_add_empty(mlcl,"mlit");
if(mlit) {
g = g && daap_add_char(mlit,"mikd",2); /* audio */
g = g && daap_add_string(mlit,"asal",current->album);
g = g && daap_add_string(mlit,"asar",current->artist);
g = g && daap_add_short(mlit,"asbt",0); /* bpm */
g = g && daap_add_short(mlit,"asbr",128); /* bitrate!! */
g = g && daap_add_string(mlit,"ascm","ron was here"); /* comment */
g = g && daap_add_char(mlit,"asco",0x0); /* compilation */
g = g && daap_add_string(mlit,"ascp",""); /* composer */
g = g && daap_add_int(mlit,"asda",0); /* date added */
g = g && daap_add_int(mlit,"asdm",0); /* date modified */
g = g && daap_add_short(mlit,"asdc",0); /* # of discs */
g = g && daap_add_short(mlit,"asdn",0); /* disc number */
g = g && daap_add_char(mlit,"asdk",0); /* song datakind? */
g = g && daap_add_string(mlit,"asfm","mp3"); /* song format */
// aseq - null string!
g = g && daap_add_string(mlit,"asgn",current->genre); /* genre */
g = g && daap_add_int(mlit,"miid",current->id); /* id */
g = g && daap_add_string(mlit,"asdt","MPEG audio file"); /* descr */
g = g && daap_add_string(mlit,"minm",current->fname); /* descr */
// mper (long)
g = g && daap_add_char(mlit,"asdb",0); /* disabled */
g = g && daap_add_char(mlit,"asrv",0); /* rel vol */
g = g && daap_add_int(mlit,"assr",44100); /* sample rate */
g = g && daap_add_int(mlit,"assz",1024); /* FIXME: Song size! */
g = g && daap_add_int(mlit,"asst",0); /* song start time? */
g = g && daap_add_int(mlit,"assp",0); /* songstoptime */
g = g && daap_add_int(mlit,"astm",3600); /* song time */
g = g && daap_add_short(mlit,"astc",0); /* track count */
g = g && daap_add_short(mlit,"astn",0); /* track number */
g = g && daap_add_char(mlit,"asur",3); /* rating */
g = g && daap_add_short(mlit,"asyr",0);
} else g=0;
} }
} else g=0;
}
db_enum_end();
if(!g) { if(!g) {
daap_free(root); daap_free(root);
@ -236,15 +287,19 @@ DAAP_BLOCK *daap_response_songlist(void) {
* handle the daap block for the /update URI * handle the daap block for the /update URI
*/ */
DAAP_BLOCK *daap_response_update(void) { DAAP_BLOCK *daap_response_update(int clientver) {
DAAP_BLOCK *root; DAAP_BLOCK *root;
int g=1; int g=1;
while(clientver == db_version()) {
sleep(30);
}
root=daap_add_empty(NULL,"mupd"); root=daap_add_empty(NULL,"mupd");
if(root) { if(root) {
g = (int)daap_add_int(root,"mstt",200); g = (int)daap_add_int(root,"mstt",200);
/* theoretically, this would go up if the db changes? */ /* theoretically, this would go up if the db changes? */
g = g && daap_add_int(root,"musr",3); g = g && daap_add_int(root,"musr",db_version());
} }
if(!g) { if(!g) {
@ -373,7 +428,7 @@ DAAP_BLOCK *daap_response_playlists(void) {
g = g && daap_add_int(mlit,"miid",0x1); g = g && daap_add_int(mlit,"miid",0x1);
g = g && daap_add_long(mlit,"mper",0,2); g = g && daap_add_long(mlit,"mper",0,2);
g = g && daap_add_string(mlit,"minm","daapd music"); g = g && daap_add_string(mlit,"minm","daapd music");
g = g && daap_add_int(mlit,"mimc",0x0); g = g && daap_add_int(mlit,"mimc",db_get_song_count());
} }
} }
} }
@ -414,7 +469,7 @@ DAAP_BLOCK *daap_response_dbinfo(void) {
g = g && daap_add_int(mlit,"miid",0x20); g = g && daap_add_int(mlit,"miid",0x20);
g = g && daap_add_long(mlit,"mper",0,1); g = g && daap_add_long(mlit,"mper",0,1);
g = g && daap_add_string(mlit,"minm","daapd music"); g = g && daap_add_string(mlit,"minm","daapd music");
g = g && daap_add_int(mlit,"mimc",0x0); /* songs */ g = g && daap_add_int(mlit,"mimc",db_get_song_count()); /* songs */
g = g && daap_add_int(mlit,"mctc",0x1); /* playlists */ g = g && daap_add_int(mlit,"mctc",0x1); /* playlists */
} }
} }
@ -476,8 +531,15 @@ DAAP_BLOCK *daap_response_server_info(void) {
*/ */
DAAP_BLOCK *daap_response_playlist_items(int playlist) { DAAP_BLOCK *daap_response_playlist_items(int playlist) {
DAAP_BLOCK *root; DAAP_BLOCK *root;
DAAP_BLOCK *mlcl;
DAAP_BLOCK *mlit;
ENUMHANDLE henum;
MP3FILE *current;
int g=1; int g=1;
henum=db_enum_begin();
if(!henum)
return NULL;
root=daap_add_empty(NULL,"apso"); root=daap_add_empty(NULL,"apso");
if(root) { if(root) {
@ -485,8 +547,22 @@ DAAP_BLOCK *daap_response_playlist_items(int playlist) {
g = g && daap_add_char(root,"muty",0); g = g && daap_add_char(root,"muty",0);
g = g && daap_add_int(root,"mtco",0); g = g && daap_add_int(root,"mtco",0);
g = g && daap_add_int(root,"mrco",0); g = g && daap_add_int(root,"mrco",0);
g = g && daap_add_empty(root,"mlcl");
mlcl=daap_add_empty(root,"mlcl");
if(mlcl) {
while(current=db_enum(&henum)) {
mlit=daap_add_empty(mlcl,"mlit");
if(mlit) {
g = g && daap_add_char(mlit,"mikd",2);
g = g && daap_add_int(mlit,"miid",current->id);
g = g && daap_add_int(mlit,"mcti",0x1); /* built-in container */
} else g=0;
} }
} else g=0;
}
db_enum_end();
if(!g) { if(!g) {
daap_free(root); daap_free(root);

View File

@ -26,7 +26,7 @@
DAAP_BLOCK *daap_response_server_info(void); DAAP_BLOCK *daap_response_server_info(void);
DAAP_BLOCK *daap_response_content_codes(void); DAAP_BLOCK *daap_response_content_codes(void);
DAAP_BLOCK *daap_response_login(void); DAAP_BLOCK *daap_response_login(void);
DAAP_BLOCK *daap_response_update(void); DAAP_BLOCK *daap_response_update(int clientver);
DAAP_BLOCK *daap_response_databases(char *path); DAAP_BLOCK *daap_response_databases(char *path);
#endif /* _DAAP_H_ */ #endif /* _DAAP_H_ */

View File

@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "err.h"
#include "mp3-scanner.h" #include "mp3-scanner.h"
/* /*
@ -40,10 +41,11 @@ typedef struct tag_mp3record {
* Globals * Globals
*/ */
MP3RECORD db_root; MP3RECORD db_root;
int db_version; int db_version_no;
int db_update_mode=0; int db_update_mode=0;
pthread_rwlock_t db_rwlock=PTHREAD_RWLOCK_INITIALIZER; int db_song_count;
pthread_rwlock_t db_rwlock; /* OSX doesn't have PTHREAD_RWLOCK_INITIALIZER */
pthread_once_t db_initlock=PTHREAD_ONCE_INIT;
/* /*
* Forwards * Forwards
*/ */
@ -56,8 +58,24 @@ int db_deinit(void);
int db_version(void); int db_version(void);
int db_add(MP3FILE *mp3file); int db_add(MP3FILE *mp3file);
MP3RECORD *db_enum_begin(void);
MP3FILE *db_enum(MP3RECORD **current);
int db_enum_end(void);
int db_get_song_count(void);
MP3FILE *db_find(int id);
void db_freerecord(MP3RECORD *mp3record); void db_freerecord(MP3RECORD *mp3record);
/*
* db_init_once
*
* Must dynamically initialize the rwlock, as Mac OSX 10.3 (at least)
* doesn't have a static initializer for rwlocks
*/
void db_init_once(void) {
pthread_rwlock_init(&db_rwlock,NULL);
}
/* /*
* db_init * db_init
* *
@ -66,7 +84,10 @@ void db_freerecord(MP3RECORD *mp3record);
*/ */
int db_init(char *parameters) { int db_init(char *parameters) {
db_root.next=NULL; db_root.next=NULL;
return 0; db_version_no=1;
db_song_count=0;
return pthread_once(&db_initlock,db_init_once);
} }
/* /*
@ -85,7 +106,7 @@ int db_deinit(void) {
* return the db version * return the db version
*/ */
int db_version(void) { int db_version(void) {
return db_version; return db_version_no;
} }
/* /*
@ -116,7 +137,7 @@ int db_end_initial_update(void) {
* background update mode * background update mode
*/ */
int db_is_empty(void) { int db_is_empty(void) {
return db_root.next; return !db_root.next;
} }
/* /*
@ -127,9 +148,12 @@ int db_is_empty(void) {
int db_add(MP3FILE *mp3file) { int db_add(MP3FILE *mp3file) {
int err; int err;
int g;
MP3RECORD *pnew; MP3RECORD *pnew;
if(!pnew=(MP3RECORD*)malloc(sizeof(MP3RECORD))) { DPRINTF(ERR_DEBUG,"Adding %s\n",mp3file->path);
if((pnew=(MP3RECORD*)malloc(sizeof(MP3RECORD))) == NULL) {
free(pnew); free(pnew);
errno=ENOMEM; errno=ENOMEM;
return -1; return -1;
@ -137,29 +161,40 @@ int db_add(MP3FILE *mp3file) {
memset(pnew,0,sizeof(MP3RECORD)); memset(pnew,0,sizeof(MP3RECORD));
memcpy(pnew->mp3file,mp3file,sizeof(MP3FILE)); memcpy(&pnew->mp3file,mp3file,sizeof(MP3FILE));
err=(int) pnew->mp3file.path=strdup(mp3file->path);
err = err | pnew->mp3file.fname=strdup(mp3file->fname);
err = err | pnew->mp3file.artist=strdup(mp3file->artist);
err = err | pnew->mp3file.album=strdup(mp3file->album);
err = err | pnew->mp3file.genre=strdup(mp3file->genre);
if(err) { g=(int) pnew->mp3file.path=strdup(mp3file->path);
g = g && (pnew->mp3file.fname=strdup(mp3file->fname));
g = g && (pnew->mp3file.artist=strdup(mp3file->artist));
g = g && (pnew->mp3file.album=strdup(mp3file->album));
g = g && (pnew->mp3file.genre=strdup(mp3file->genre));
if(!g) {
DPRINTF(ERR_WARN,"Malloc error in db_add\n");
db_freerecord(pnew); db_freerecord(pnew);
errno=ENOMEM; errno=ENOMEM;
return -1; return -1;
} }
if(err=pthread_rwlock_wrlock(&db_wrlock)) { if(err=pthread_rwlock_wrlock(&db_rwlock)) {
DPRINTF(ERR_WARN,"cannot lock wrlock in db_add\n");
db_freerecord(pnew); db_freerecord(pnew);
errno=err; errno=err;
return -1; return -1;
} }
pnew->next=root.next; pnew->next=db_root.next;
root.next=pnew->next; db_root.next=pnew;
pthread_rwlock_unlock(&db_wrlock); if(!db_update_mode) {
db_version_no++;
}
db_song_count++;
pthread_rwlock_unlock(&db_rwlock);
DPRINTF(ERR_DEBUG,"Added file\n");
return 0;
} }
/* /*
@ -176,3 +211,76 @@ void db_freerecord(MP3RECORD *mp3record) {
free(mp3record); free(mp3record);
} }
/*
* db_enum_begin
*
* Begin to walk through an enum of
* the database.
*
* this should be done quickly, as we'll be holding
* a reader lock on the db
*/
MP3RECORD *db_enum_begin(void) {
int err;
if(err=pthread_rwlock_wrlock(&db_rwlock)) {
log_err(0,"Cannot lock rwlock\n");
errno=err;
return NULL;
}
return db_root.next;
}
/*
* db_enum
*
* Walk to the next entry
*/
MP3FILE *db_enum(MP3RECORD **current) {
MP3FILE *retval;
if(*current) {
retval=&((*current)->mp3file);
*current=(*current)->next;
return retval;
}
return NULL;
}
/*
* db_enum_end
*
* quit walking the database (and give up reader lock)
*/
int db_enum_end(void) {
return pthread_rwlock_unlock(&db_rwlock);
}
/*
* db_find
*
* Find a MP3FILE entry based on file id
*/
MP3FILE *db_find(int id) {
MP3RECORD *current=db_root.next;
while((current) && (current->mp3file.id != id)) {
current=current->next;
}
if(!current)
return NULL;
return &current->mp3file;
}
/*
* db_get_song_count
*
* return the number of songs in the database. Used for the /database
* request
*/
int db_get_song_count(void) {
return db_song_count;
}

View File

@ -35,7 +35,9 @@ extern int db_version(void);
extern int db_add(MP3FILE *mp3file); extern int db_add(MP3FILE *mp3file);
extern ENUMHANDLE db_enum_begin(void); extern ENUMHANDLE db_enum_begin(void);
extern MP3FILE *db_enum(ENUMHANDLE *current); extern MP3FILE *db_enum(ENUMHANDLE *current);
extern int db_enum_end(ENUMHANDLE current); extern int db_enum_end(void);
extern MP3FILE *db_find(int id); extern MP3FILE *db_find(int id);
extern int db_get_song_count(void);
#endif /* _DB_MEMORY_H_ */ #endif /* _DB_MEMORY_H_ */

View File

@ -36,9 +36,11 @@
#include <sys/types.h> #include <sys/types.h>
#include "configfile.h" #include "configfile.h"
#include "db-memory.h"
#include "daap.h" #include "daap.h"
#include "daap-proto.h" #include "daap-proto.h"
#include "err.h" #include "err.h"
#include "mp3-scanner.h"
#include "rend.h" #include "rend.h"
#include "webserver.h" #include "webserver.h"
@ -61,6 +63,7 @@ void daap_handler(WS_CONNINFO *pwsc) {
int close; int close;
DAAP_BLOCK *root,*error; DAAP_BLOCK *root,*error;
int compress=0; int compress=0;
int clientrev;
close=pwsc->close; close=pwsc->close;
pwsc->close=1; pwsc->close=1;
@ -77,7 +80,12 @@ void daap_handler(WS_CONNINFO *pwsc) {
} else if (!strcasecmp(pwsc->uri,"/login")) { } else if (!strcasecmp(pwsc->uri,"/login")) {
root=daap_response_login(); root=daap_response_login();
} else if (!strcasecmp(pwsc->uri,"/update")) { } else if (!strcasecmp(pwsc->uri,"/update")) {
root=daap_response_update(); if(!ws_getvar(pwsc,"revision-number")) { /* first check */
clientrev=db_version() - 1;
} else {
clientrev=atoi(ws_getvar(pwsc,"revision-number"));
}
root=daap_response_update(clientrev);
} else if (!strcasecmp(pwsc->uri,"/databases")) { } else if (!strcasecmp(pwsc->uri,"/databases")) {
root=daap_response_databases(pwsc->uri); root=daap_response_databases(pwsc->uri);
} else if (!strcasecmp(pwsc->uri,"/logout")) { } else if (!strcasecmp(pwsc->uri,"/logout")) {
@ -250,6 +258,8 @@ int main(int argc, char *argv[]) {
WSHANDLE server; WSHANDLE server;
pid_t rendezvous_pid; pid_t rendezvous_pid;
int use_mdns=0; int use_mdns=0;
ENUMHANDLE handle;
MP3FILE *pmp3;
#ifdef DEBUG #ifdef DEBUG
char *optval="d:c:m"; char *optval="d:c:m";
@ -299,8 +309,27 @@ int main(int argc, char *argv[]) {
} }
} }
/* should verify the configfile has enough info /* Initialize the database before starting */
* to start */ if(db_init("none")) {
perror("db_init");
exit(EXIT_FAILURE);
}
if(scan_init(config.mp3dir)) {
perror("scan_init");
exit(EXIT_FAILURE);
}
#ifdef DEBUG
printf("Dump of database:\n");
handle=db_enum_begin();
while(pmp3=db_enum(&handle)) {
printf("File: %s\n",pmp3->fname);
}
db_enum_end();
#endif
/* start up the web server */ /* start up the web server */
ws_config.web_root=config.web_root; ws_config.web_root=config.web_root;

View File

@ -31,4 +31,6 @@ typedef struct tag_mp3file {
int id; int id;
} MP3FILE; } MP3FILE;
extern int scan_init(char *path);
#endif /* _MP3_SCANNER_H_ */ #endif /* _MP3_SCANNER_H_ */