* Fix some possible memory leaks.
* Pay attention to the specified port number. * Add support for multiple media directories, and allow content filtering on the directories.
This commit is contained in:
parent
3f454a5762
commit
0324818d86
@ -222,6 +222,7 @@ find_album_art(const char * path)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
sqlite3_free(sql);
|
||||||
sql = sqlite3_mprintf( "INSERT into ALBUM_ART"
|
sql = sqlite3_mprintf( "INSERT into ALBUM_ART"
|
||||||
" (PATH, EMBEDDED) "
|
" (PATH, EMBEDDED) "
|
||||||
"VALUES"
|
"VALUES"
|
||||||
@ -231,6 +232,7 @@ find_album_art(const char * path)
|
|||||||
if( sql_exec(db, sql) == SQLITE_OK )
|
if( sql_exec(db, sql) == SQLITE_OK )
|
||||||
ret = sqlite3_last_insert_rowid(db);
|
ret = sqlite3_last_insert_rowid(db);
|
||||||
}
|
}
|
||||||
|
sqlite3_free_table(result);
|
||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
}
|
}
|
||||||
if( album_art )
|
if( album_art )
|
||||||
|
37
getifaddr.c
37
getifaddr.c
@ -59,17 +59,34 @@ getifaddr(const char * ifname, char * buf, int len)
|
|||||||
int
|
int
|
||||||
getsysaddr(char * buf, int len)
|
getsysaddr(char * buf, int len)
|
||||||
{
|
{
|
||||||
char hn[256];
|
int i;
|
||||||
struct in_addr *addr;
|
int s = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
struct hostent *host;
|
|
||||||
|
|
||||||
memset(buf, '\0', len);
|
for (i=1; i > 0; i++)
|
||||||
gethostname(hn, sizeof(hn));
|
{
|
||||||
host = gethostbyname(hn);
|
struct ifreq ifr;
|
||||||
if( !host )
|
struct sockaddr_in *addr = (struct sockaddr_in *) &ifr.ifr_addr;
|
||||||
return -1;
|
|
||||||
addr = (struct in_addr*)host->h_addr;
|
ifr.ifr_ifindex = i;
|
||||||
strncpy(buf, inet_ntoa(*addr), len);
|
if( ioctl(s, SIOCGIFNAME, &ifr) < 0 )
|
||||||
|
break;
|
||||||
|
if(ioctl(s, SIOCGIFADDR, &ifr, sizeof(struct ifreq)) < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
|
||||||
|
close(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(strncmp(inet_ntoa(addr->sin_addr), "127.", 4) == 0)
|
||||||
|
continue;
|
||||||
|
if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len))
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "inet_ntop(): %m");
|
||||||
|
close(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
165
minidlna.c
165
minidlna.c
@ -139,17 +139,6 @@ set_startup_time(int sysuptime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* structure containing variables used during "main loop"
|
|
||||||
* that are filled during the init */
|
|
||||||
struct runtime_vars {
|
|
||||||
/* LAN IP addresses for SSDP traffic and HTTP */
|
|
||||||
/* moved to global vars */
|
|
||||||
/*int n_lan_addr;*/
|
|
||||||
/*struct lan_addr_s lan_addr[MAX_LAN_ADDR];*/
|
|
||||||
int port; /* HTTP Port */
|
|
||||||
int notify_interval; /* seconds between SSDP announces */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* parselanaddr()
|
/* parselanaddr()
|
||||||
* parse address with mask
|
* parse address with mask
|
||||||
* ex: 192.168.1.1/24
|
* ex: 192.168.1.1/24
|
||||||
@ -224,7 +213,7 @@ getfriendlyname(char * buf, int len)
|
|||||||
* 7) compute presentation URL
|
* 7) compute presentation URL
|
||||||
* 8) set signal handlers */
|
* 8) set signal handlers */
|
||||||
static int
|
static int
|
||||||
init(int argc, char * * argv, struct runtime_vars * v)
|
init(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int pid;
|
int pid;
|
||||||
@ -261,7 +250,6 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
|
|
||||||
getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
|
getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
|
||||||
|
|
||||||
/*v->n_lan_addr = 0;*/
|
|
||||||
char ext_ip_addr[INET_ADDRSTRLEN];
|
char ext_ip_addr[INET_ADDRSTRLEN];
|
||||||
if( (getsysaddr(ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
|
if( (getsysaddr(ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
|
||||||
(getifaddr("eth0", ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
|
(getifaddr("eth0", ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
|
||||||
@ -272,8 +260,8 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
}
|
}
|
||||||
if( parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0 )
|
if( parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0 )
|
||||||
n_lan_addr++;
|
n_lan_addr++;
|
||||||
v->port = -1;
|
runtime_vars.port = -1;
|
||||||
v->notify_interval = 30; /* seconds between SSDP announces */
|
runtime_vars.notify_interval = 30; /* seconds between SSDP announces */
|
||||||
|
|
||||||
/* read options file first since
|
/* read options file first since
|
||||||
* command line arguments have final say */
|
* command line arguments have final say */
|
||||||
@ -290,12 +278,11 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
switch(ary_options[i].id)
|
switch(ary_options[i].id)
|
||||||
{
|
{
|
||||||
case UPNPLISTENING_IP:
|
case UPNPLISTENING_IP:
|
||||||
if(n_lan_addr < MAX_LAN_ADDR)/* if(v->n_lan_addr < MAX_LAN_ADDR)*/
|
if(n_lan_addr < MAX_LAN_ADDR)
|
||||||
{
|
{
|
||||||
/*if(parselanaddr(&v->lan_addr[v->n_lan_addr],*/
|
|
||||||
if(parselanaddr(&lan_addr[n_lan_addr],
|
if(parselanaddr(&lan_addr[n_lan_addr],
|
||||||
ary_options[i].value) == 0)
|
ary_options[i].value) == 0)
|
||||||
n_lan_addr++; /*v->n_lan_addr++; */
|
n_lan_addr++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -304,13 +291,13 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UPNPPORT:
|
case UPNPPORT:
|
||||||
v->port = atoi(ary_options[i].value);
|
runtime_vars.port = atoi(ary_options[i].value);
|
||||||
break;
|
break;
|
||||||
case UPNPPRESENTATIONURL:
|
case UPNPPRESENTATIONURL:
|
||||||
presurl = ary_options[i].value;
|
presurl = ary_options[i].value;
|
||||||
break;
|
break;
|
||||||
case UPNPNOTIFY_INTERVAL:
|
case UPNPNOTIFY_INTERVAL:
|
||||||
v->notify_interval = atoi(ary_options[i].value);
|
runtime_vars.notify_interval = atoi(ary_options[i].value);
|
||||||
break;
|
break;
|
||||||
case UPNPSYSTEM_UPTIME:
|
case UPNPSYSTEM_UPTIME:
|
||||||
if(strcmp(ary_options[i].value, "yes") == 0)
|
if(strcmp(ary_options[i].value, "yes") == 0)
|
||||||
@ -337,8 +324,54 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
friendly_name[FRIENDLYNAME_MAX_LEN-1] = '\0';
|
friendly_name[FRIENDLYNAME_MAX_LEN-1] = '\0';
|
||||||
break;
|
break;
|
||||||
case UPNPMEDIADIR:
|
case UPNPMEDIADIR:
|
||||||
strncpy(media_dir, ary_options[i].value, MEDIADIR_MAX_LEN);
|
usleep(1);
|
||||||
media_dir[MEDIADIR_MAX_LEN-1] = '\0';
|
enum media_types type = ALL_MEDIA;
|
||||||
|
char * myval = NULL;
|
||||||
|
switch( ary_options[i].value[0] )
|
||||||
|
{
|
||||||
|
case 'A':
|
||||||
|
case 'a':
|
||||||
|
if( ary_options[i].value[0] == 'A' || ary_options[i].value[0] == 'a' )
|
||||||
|
type = AUDIO_ONLY;
|
||||||
|
case 'V':
|
||||||
|
case 'v':
|
||||||
|
if( ary_options[i].value[0] == 'V' || ary_options[i].value[0] == 'v' )
|
||||||
|
type = VIDEO_ONLY;
|
||||||
|
case 'P':
|
||||||
|
case 'p':
|
||||||
|
if( ary_options[i].value[0] == 'P' || ary_options[i].value[0] == 'p' )
|
||||||
|
type = IMAGES_ONLY;
|
||||||
|
myval = index(ary_options[i].value, '/');
|
||||||
|
case '/':
|
||||||
|
usleep(1);
|
||||||
|
char * path = realpath(myval ? myval:ary_options[i].value, NULL);
|
||||||
|
if( access(path, F_OK) != 0 )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Media directory not accessible! [%s]\n",
|
||||||
|
path);
|
||||||
|
free(path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
struct media_dir_s * this_dir = calloc(1, sizeof(struct media_dir_s));
|
||||||
|
this_dir->path = path;
|
||||||
|
this_dir->type = type;
|
||||||
|
if( !media_dirs )
|
||||||
|
{
|
||||||
|
media_dirs = this_dir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct media_dir_s * all_dirs = media_dirs;
|
||||||
|
while( all_dirs->next )
|
||||||
|
all_dirs = all_dirs->next;
|
||||||
|
all_dirs->next = this_dir;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Media directory entry not understood! [%s]\n",
|
||||||
|
ary_options[i].value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown option in file %s\n",
|
fprintf(stderr, "Unknown option in file %s\n",
|
||||||
@ -358,7 +391,7 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
{
|
{
|
||||||
case 't':
|
case 't':
|
||||||
if(i+1 < argc)
|
if(i+1 < argc)
|
||||||
v->notify_interval = atoi(argv[++i]);
|
runtime_vars.notify_interval = atoi(argv[++i]);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
|
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
|
||||||
break;
|
break;
|
||||||
@ -392,7 +425,7 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if(i+1 < argc)
|
if(i+1 < argc)
|
||||||
v->port = atoi(argv[++i]);
|
runtime_vars.port = atoi(argv[++i]);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
|
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
|
||||||
break;
|
break;
|
||||||
@ -417,22 +450,19 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
int address_already_there = 0;
|
int address_already_there = 0;
|
||||||
int j;
|
int j;
|
||||||
i++;
|
i++;
|
||||||
for(j=0; j<n_lan_addr; j++)/* for(j=0; j<v->n_lan_addr; j++)*/
|
for(j=0; j<n_lan_addr; j++)
|
||||||
{
|
{
|
||||||
struct lan_addr_s tmpaddr;
|
struct lan_addr_s tmpaddr;
|
||||||
parselanaddr(&tmpaddr, argv[i]);
|
parselanaddr(&tmpaddr, argv[i]);
|
||||||
/*if(0 == strcmp(v->lan_addr[j].str, tmpaddr.str))*/
|
|
||||||
if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
|
if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
|
||||||
address_already_there = 1;
|
address_already_there = 1;
|
||||||
}
|
}
|
||||||
if(address_already_there)
|
if(address_already_there)
|
||||||
break;
|
break;
|
||||||
if(n_lan_addr < MAX_LAN_ADDR) /*if(v->n_lan_addr < MAX_LAN_ADDR)*/
|
if(n_lan_addr < MAX_LAN_ADDR)
|
||||||
{
|
{
|
||||||
/*v->lan_addr[v->n_lan_addr++] = argv[i];*/
|
|
||||||
/*if(parselanaddr(&v->lan_addr[v->n_lan_addr], argv[i]) == 0)*/
|
|
||||||
if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)
|
if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)
|
||||||
n_lan_addr++; /*v->n_lan_addr++;*/
|
n_lan_addr++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -450,7 +480,7 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( (/*v->*/n_lan_addr==0) || (v->port<=0) )
|
if( (n_lan_addr==0) || (runtime_vars.port<=0) )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage:\n\t"
|
fprintf(stderr, "Usage:\n\t"
|
||||||
"%s [-f config_file] [-i ext_ifname] [-o ext_ip]\n"
|
"%s [-f config_file] [-i ext_ifname] [-o ext_ip]\n"
|
||||||
@ -521,8 +551,6 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
|||||||
{
|
{
|
||||||
snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
|
snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
|
||||||
"http://%s/", lan_addr[0].str);
|
"http://%s/", lan_addr[0].str);
|
||||||
/*"http://%s:%d/", lan_addr[0].str, 80);*/
|
|
||||||
/*"http://%s:%d/", v->lan_addr[0].str, 80);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set signal handler */
|
/* set signal handler */
|
||||||
@ -566,19 +594,36 @@ main(int argc, char * * argv)
|
|||||||
#endif
|
#endif
|
||||||
struct timeval timeout, timeofday, lasttimeofday = {0, 0};
|
struct timeval timeout, timeofday, lasttimeofday = {0, 0};
|
||||||
int max_fd = -1;
|
int max_fd = -1;
|
||||||
struct runtime_vars v;
|
|
||||||
|
|
||||||
if(init(argc, argv, &v) != 0)
|
if(init(argc, argv) != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
LIST_INIT(&upnphttphead);
|
LIST_INIT(&upnphttphead);
|
||||||
|
|
||||||
if( access(DB_PATH, F_OK) )
|
if( access(DB_PATH, F_OK) )
|
||||||
{
|
{
|
||||||
|
struct media_dir_s * media_path = media_dirs;
|
||||||
sqlite3_open(DB_PATH, &db);
|
sqlite3_open(DB_PATH, &db);
|
||||||
freopen("/dev/null", "a", stderr);
|
freopen("/dev/null", "a", stderr);
|
||||||
ScanDirectory(media_dir, NULL);
|
if( CreateDatabase() != 0 )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error creating database!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if USE_FORK
|
||||||
|
pid_t newpid = fork();
|
||||||
|
if( newpid )
|
||||||
|
goto fork_done;
|
||||||
|
#endif
|
||||||
|
while( media_path )
|
||||||
|
{
|
||||||
|
ScanDirectory(media_path->path, NULL, media_path->type);
|
||||||
|
media_path = media_path->next;
|
||||||
|
}
|
||||||
freopen("/proc/self/fd/2", "a", stderr);
|
freopen("/proc/self/fd/2", "a", stderr);
|
||||||
|
#if USE_FORK
|
||||||
|
_exit(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -588,21 +633,40 @@ main(int argc, char * * argv)
|
|||||||
if( sqlite3_get_table(db, "pragma user_version", &result, &rows, 0, 0) == SQLITE_OK )
|
if( sqlite3_get_table(db, "pragma user_version", &result, &rows, 0, 0) == SQLITE_OK )
|
||||||
{
|
{
|
||||||
if( atoi(result[1]) != DB_VERSION ) {
|
if( atoi(result[1]) != DB_VERSION ) {
|
||||||
|
struct media_dir_s * media_path = media_dirs;
|
||||||
printf("Database version mismatch; need to recreate...\n");
|
printf("Database version mismatch; need to recreate...\n");
|
||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
unlink(DB_PATH);
|
unlink(DB_PATH);
|
||||||
sqlite3_open(DB_PATH, &db);
|
sqlite3_open(DB_PATH, &db);
|
||||||
freopen("/dev/null", "a", stderr);
|
freopen("/dev/null", "a", stderr);
|
||||||
ScanDirectory(media_dir, NULL);
|
if( CreateDatabase() != 0 )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error creating database!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if USE_FORK
|
||||||
|
pid_t newpid = fork();
|
||||||
|
if( newpid )
|
||||||
|
goto fork_done;
|
||||||
|
#endif
|
||||||
|
while( media_path )
|
||||||
|
{
|
||||||
|
ScanDirectory(media_path->path, NULL, media_path->type);
|
||||||
|
media_path = media_path->next;
|
||||||
|
}
|
||||||
|
ScanDirectory(media_dirs->path, NULL, media_dirs->type);
|
||||||
freopen("/proc/self/fd/2", "a", stderr);
|
freopen("/proc/self/fd/2", "a", stderr);
|
||||||
|
#if USE_FORK
|
||||||
|
_exit(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
sqlite3_free_table(result);
|
sqlite3_free_table(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if USE_FORK
|
||||||
|
fork_done:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* open socket for SSDP connections */
|
|
||||||
/*sudp = OpenAndConfSSDPReceiveSocket(v.n_lan_addr, v.lan_addr);*/
|
|
||||||
sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);
|
sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);
|
||||||
if(sudp < 0)
|
if(sudp < 0)
|
||||||
{
|
{
|
||||||
@ -610,13 +674,13 @@ main(int argc, char * * argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* open socket for HTTP connections. Listen on the 1st LAN address */
|
/* open socket for HTTP connections. Listen on the 1st LAN address */
|
||||||
shttpl = OpenAndConfHTTPSocket(v.port);
|
shttpl = OpenAndConfHTTPSocket(runtime_vars.port);
|
||||||
if(shttpl < 0)
|
if(shttpl < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
|
syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
|
syslog(LOG_NOTICE, "HTTP listening on port %d", runtime_vars.port);
|
||||||
|
|
||||||
/* open socket for sending notifications */
|
/* open socket for sending notifications */
|
||||||
if(OpenAndConfSSDPNotifySockets(snotify) < 0)
|
if(OpenAndConfSSDPNotifySockets(snotify) < 0)
|
||||||
@ -636,24 +700,24 @@ main(int argc, char * * argv)
|
|||||||
if(gettimeofday(&timeofday, 0) < 0)
|
if(gettimeofday(&timeofday, 0) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "gettimeofday(): %m");
|
syslog(LOG_ERR, "gettimeofday(): %m");
|
||||||
timeout.tv_sec = v.notify_interval;
|
timeout.tv_sec = runtime_vars.notify_interval;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* the comparaison is not very precise but who cares ? */
|
/* the comparaison is not very precise but who cares ? */
|
||||||
if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))
|
if(timeofday.tv_sec >= (lasttimeofday.tv_sec + runtime_vars.notify_interval))
|
||||||
{
|
{
|
||||||
SendSSDPNotifies2(snotify,
|
SendSSDPNotifies2(snotify,
|
||||||
(unsigned short)v.port,
|
(unsigned short)runtime_vars.port,
|
||||||
(v.notify_interval << 1)+10);
|
(runtime_vars.notify_interval << 1)+10);
|
||||||
memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
|
memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
|
||||||
timeout.tv_sec = v.notify_interval;
|
timeout.tv_sec = runtime_vars.notify_interval;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
|
timeout.tv_sec = lasttimeofday.tv_sec + runtime_vars.notify_interval
|
||||||
- timeofday.tv_sec;
|
- timeofday.tv_sec;
|
||||||
if(timeofday.tv_usec > lasttimeofday.tv_usec)
|
if(timeofday.tv_usec > lasttimeofday.tv_usec)
|
||||||
{
|
{
|
||||||
@ -724,8 +788,7 @@ main(int argc, char * * argv)
|
|||||||
if(sudp >= 0 && FD_ISSET(sudp, &readset))
|
if(sudp >= 0 && FD_ISSET(sudp, &readset))
|
||||||
{
|
{
|
||||||
/*syslog(LOG_INFO, "Received UDP Packet");*/
|
/*syslog(LOG_INFO, "Received UDP Packet");*/
|
||||||
/*ProcessSSDPRequest(sudp, v.lan_addr, v.n_lan_addr,*/
|
ProcessSSDPRequest(sudp, (unsigned short)runtime_vars.port);
|
||||||
ProcessSSDPRequest(sudp, (unsigned short)v.port);
|
|
||||||
}
|
}
|
||||||
/* process active HTTP connections */
|
/* process active HTTP connections */
|
||||||
/* LIST_FOREACH macro is not available under linux */
|
/* LIST_FOREACH macro is not available under linux */
|
||||||
@ -802,7 +865,7 @@ shutdown:
|
|||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
|
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
|
||||||
}
|
}
|
||||||
for(i=0; i<n_lan_addr; i++)/* for(i=0; i<v.n_lan_addr; i++)*/
|
for(i=0; i<n_lan_addr; i++)
|
||||||
close(snotify[i]);
|
close(snotify[i]);
|
||||||
|
|
||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
|
@ -4,6 +4,13 @@ port=5555
|
|||||||
# enable UPNP support (default is yes)
|
# enable UPNP support (default is yes)
|
||||||
enable_upnp=yes
|
enable_upnp=yes
|
||||||
|
|
||||||
|
# set this to the directory you want scanned.
|
||||||
|
# * if have multiple directories, you can have multiple media_dir= lines
|
||||||
|
# * if you want to restrict a media_dir to a specific content type, you
|
||||||
|
# can prepend the type, followed by a comma, to the directory:
|
||||||
|
# + "A" for audio (eg. media_dir=A,/home/jmaggard/Music)
|
||||||
|
# + "V" for video (eg. media_dir=V,/home/jmaggard/Videos)
|
||||||
|
# + "P" for images (eg. media_dir=P,/home/jmaggard/Pictures)
|
||||||
media_dir=/opt
|
media_dir=/opt
|
||||||
|
|
||||||
# set this if you want to customize the name that shows up on your clients
|
# set this if you want to customize the name that shows up on your clients
|
||||||
|
@ -16,4 +16,22 @@ struct lan_addr_s {
|
|||||||
struct in_addr addr, mask; /* ip/mask */
|
struct in_addr addr, mask; /* ip/mask */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct runtime_vars_s {
|
||||||
|
int port; /* HTTP Port */
|
||||||
|
int notify_interval; /* seconds between SSDP announces */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum media_types {
|
||||||
|
ALL_MEDIA,
|
||||||
|
AUDIO_ONLY,
|
||||||
|
VIDEO_ONLY,
|
||||||
|
IMAGES_ONLY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct media_dir_s {
|
||||||
|
char * path; /* Base path */
|
||||||
|
enum media_types type; /* type of files to scan */
|
||||||
|
struct media_dir_s * next;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
150
scanner.c
150
scanner.c
@ -57,6 +57,26 @@ is_image(const char * file)
|
|||||||
return (ends_with(file, ".jpg") || ends_with(file, ".jpeg"));
|
return (ends_with(file, ".jpg") || ends_with(file, ".jpeg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqlite_int64
|
||||||
|
get_next_available_id(const char * table, const char * parentID)
|
||||||
|
{
|
||||||
|
char * sql;
|
||||||
|
char **result;
|
||||||
|
int ret;
|
||||||
|
sqlite_int64 objectID = 0;
|
||||||
|
|
||||||
|
asprintf(&sql, "SELECT OBJECT_ID, max(ID) from %s where PARENT_ID = '%s'", table, parentID);
|
||||||
|
ret = sql_get_table(db, sql, &result, NULL, NULL);
|
||||||
|
if( result[2] && (sscanf(rindex(result[2], '$')+1, "%llX", &objectID) == 1) )
|
||||||
|
{
|
||||||
|
objectID++;
|
||||||
|
}
|
||||||
|
sqlite3_free_table(result);
|
||||||
|
free(sql);
|
||||||
|
|
||||||
|
return objectID;
|
||||||
|
}
|
||||||
|
|
||||||
long long int
|
long long int
|
||||||
insert_container(const char * tmpTable, const char * item, const char * rootParent, const char *subParent,
|
insert_container(const char * tmpTable, const char * item, const char * rootParent, const char *subParent,
|
||||||
const char *class, const char *artist, const char *genre, const char *album_art)
|
const char *class, const char *artist, const char *genre, const char *album_art)
|
||||||
@ -73,29 +93,13 @@ insert_container(const char * tmpTable, const char * item, const char * rootPare
|
|||||||
if( cols )
|
if( cols )
|
||||||
{
|
{
|
||||||
sscanf(result[4], "%X", &parentID);
|
sscanf(result[4], "%X", &parentID);
|
||||||
sqlite3_free_table(result);
|
asprintf(&sql, "%s$%X", rootParent, parentID);
|
||||||
sql = sqlite3_mprintf("SELECT OBJECT_ID, max(ID) from OBJECTS where PARENT_ID = '%s$%X'", rootParent, parentID);
|
objectID = get_next_available_id("OBJECTS", sql);
|
||||||
ret = sql_get_table(db, sql, &result, 0, &cols);
|
free(sql);
|
||||||
sqlite3_free(sql);
|
|
||||||
if( result[2] && (sscanf(rindex(result[2], '$')+1, "%X", &objectID) == 1) )
|
|
||||||
{
|
|
||||||
objectID++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sqlite3_free_table(result);
|
parentID = get_next_available_id("OBJECTS", rootParent);
|
||||||
sql = sqlite3_mprintf("SELECT OBJECT_ID, max(ID) from OBJECTS where PARENT_ID = '%s'", rootParent);
|
|
||||||
sql_get_table(db, sql, &result, &rows, &cols);
|
|
||||||
sqlite3_free(sql);
|
|
||||||
if( result[2] && (sscanf(rindex(result[2], '$')+1, "%X", &parentID) == 1) )
|
|
||||||
{
|
|
||||||
parentID++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
parentID = 0;
|
|
||||||
}
|
|
||||||
detailID = GetFolderMetadata(item, artist, genre, album_art);
|
detailID = GetFolderMetadata(item, artist, genre, album_art);
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, DETAIL_ID, CLASS, NAME) "
|
" (OBJECT_ID, PARENT_ID, DETAIL_ID, CLASS, NAME) "
|
||||||
@ -301,13 +305,14 @@ insert_directory(const char * name, const char * path, const char * base, const
|
|||||||
char * id_buf = NULL;
|
char * id_buf = NULL;
|
||||||
char * parent_buf = NULL;
|
char * parent_buf = NULL;
|
||||||
char **result;
|
char **result;
|
||||||
char *dir = strdup(path);
|
char *dir = NULL;
|
||||||
|
|
||||||
if( strcmp(base, BROWSEDIR_ID) != 0 )
|
if( strcmp(base, BROWSEDIR_ID) != 0 )
|
||||||
asprintf(&refID, "%s%s$%X", BROWSEDIR_ID, parentID, objectID);
|
asprintf(&refID, "%s%s$%X", BROWSEDIR_ID, parentID, objectID);
|
||||||
|
|
||||||
if( refID )
|
if( refID )
|
||||||
{
|
{
|
||||||
|
dir = strdup(path);
|
||||||
dir = dirname(dir);
|
dir = dirname(dir);
|
||||||
asprintf(&id_buf, "%s%s$%X", base, parentID, objectID);
|
asprintf(&id_buf, "%s%s$%X", base, parentID, objectID);
|
||||||
asprintf(&parent_buf, "%s%s", base, parentID);
|
asprintf(&parent_buf, "%s%s", base, parentID);
|
||||||
@ -315,19 +320,28 @@ insert_directory(const char * name, const char * path, const char * base, const
|
|||||||
{
|
{
|
||||||
sql = sqlite3_mprintf("SELECT count(OBJECT_ID) from OBJECTS where OBJECT_ID = '%s'", id_buf);
|
sql = sqlite3_mprintf("SELECT count(OBJECT_ID) from OBJECTS where OBJECT_ID = '%s'", id_buf);
|
||||||
if( (sql_get_table(db, sql, &result, NULL, NULL) == SQLITE_OK) && atoi(result[1]) )
|
if( (sql_get_table(db, sql, &result, NULL, NULL) == SQLITE_OK) && atoi(result[1]) )
|
||||||
|
{
|
||||||
|
sqlite3_free_table(result);
|
||||||
|
sqlite3_free(sql);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
sqlite3_free_table(result);
|
||||||
|
sqlite3_free(sql);
|
||||||
/* Does not exist. Need to create, and may need to create parents also */
|
/* Does not exist. Need to create, and may need to create parents also */
|
||||||
sql = sqlite3_mprintf("SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s'", refID);
|
sql = sqlite3_mprintf("SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s'", refID);
|
||||||
if( (sql_get_table(db, sql, &result, NULL, NULL) == SQLITE_OK) && atoi(result[1]) )
|
if( (sql_get_table(db, sql, &result, NULL, NULL) == SQLITE_OK) && atoi(result[1]) )
|
||||||
{
|
{
|
||||||
detailID = atoi(result[1]);
|
detailID = atoi(result[1]);
|
||||||
}
|
}
|
||||||
|
sqlite3_free_table(result);
|
||||||
|
sqlite3_free(sql);
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, REF_ID, DETAIL_ID, CLASS, NAME) "
|
" (OBJECT_ID, PARENT_ID, REF_ID, DETAIL_ID, CLASS, NAME) "
|
||||||
"VALUES"
|
"VALUES"
|
||||||
" ('%s', '%s', %Q, '%lld', '%s', '%q')",
|
" ('%s', '%s', %Q, '%lld', '%s', '%q')",
|
||||||
id_buf, parent_buf, refID, detailID, class, rindex(dir, '/')+1);
|
id_buf, parent_buf, refID, detailID, class, rindex(dir, '/')+1);
|
||||||
sql_exec(db, sql);
|
sql_exec(db, sql);
|
||||||
|
sqlite3_free(sql);
|
||||||
if( rindex(id_buf, '$') )
|
if( rindex(id_buf, '$') )
|
||||||
*rindex(id_buf, '$') = '\0';
|
*rindex(id_buf, '$') = '\0';
|
||||||
if( rindex(parent_buf, '$') )
|
if( rindex(parent_buf, '$') )
|
||||||
@ -336,8 +350,10 @@ insert_directory(const char * name, const char * path, const char * base, const
|
|||||||
*rindex(refID, '$') = '\0';
|
*rindex(refID, '$') = '\0';
|
||||||
dir = dirname(dir);
|
dir = dirname(dir);
|
||||||
}
|
}
|
||||||
sqlite3_free(sql);
|
|
||||||
free(refID);
|
free(refID);
|
||||||
|
free(parent_buf);
|
||||||
|
free(id_buf);
|
||||||
|
free(dir);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,16 +381,12 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
unsigned long int detailID = 0;
|
unsigned long int detailID = 0;
|
||||||
char base[8];
|
char base[8];
|
||||||
char * typedir_parentID;
|
char * typedir_parentID;
|
||||||
int typedir_objectID;
|
int typedir_objectID = 0;
|
||||||
|
char * baseid;
|
||||||
|
|
||||||
static long unsigned int fileno = 0;
|
static long unsigned int fileno = 0;
|
||||||
printf("Scanned %lu files...\r", fileno++); fflush(stdout);
|
printf("Scanned %lu files...\r", fileno++); fflush(stdout);
|
||||||
|
|
||||||
sprintf(objectID, "%s%s$%X", BROWSEDIR_ID, parentID, object);
|
|
||||||
typedir_parentID = strdup(parentID);
|
|
||||||
sscanf(rindex(typedir_parentID, '$')+1, "%X", &typedir_objectID);
|
|
||||||
*rindex(typedir_parentID, '$') = '\0';
|
|
||||||
|
|
||||||
if( is_image(name) )
|
if( is_image(name) )
|
||||||
{
|
{
|
||||||
strcpy(base, IMAGE_DIR_ID);
|
strcpy(base, IMAGE_DIR_ID);
|
||||||
@ -397,6 +409,15 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
if( !detailID )
|
if( !detailID )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
sprintf(objectID, "%s%s$%X", BROWSEDIR_ID, parentID, object);
|
||||||
|
typedir_parentID = strdup(parentID);
|
||||||
|
baseid = rindex(typedir_parentID, '$');
|
||||||
|
if( baseid )
|
||||||
|
{
|
||||||
|
sscanf(baseid+1, "%X", &typedir_objectID);
|
||||||
|
*baseid = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
insert_directory(name, path, base, typedir_parentID, typedir_objectID);
|
insert_directory(name, path, base, typedir_parentID, typedir_objectID);
|
||||||
|
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
@ -406,6 +427,7 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
objectID, BROWSEDIR_ID, parentID, class, detailID, name);
|
objectID, BROWSEDIR_ID, parentID, class, detailID, name);
|
||||||
//DEBUG printf("SQL: %s\n", sql);
|
//DEBUG printf("SQL: %s\n", sql);
|
||||||
sql_exec(db, sql);
|
sql_exec(db, sql);
|
||||||
|
sqlite3_free(sql);
|
||||||
|
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
||||||
@ -416,12 +438,14 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
sql_exec(db, sql);
|
sql_exec(db, sql);
|
||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
|
|
||||||
|
free(typedir_parentID);
|
||||||
|
|
||||||
insert_containers(name, path, objectID, class, detailID);
|
insert_containers(name, path, objectID, class, detailID);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
create_database(void)
|
CreateDatabase(void)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
char sql_buf[512];
|
char sql_buf[512];
|
||||||
@ -569,42 +593,52 @@ filter_media(const struct dirent *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ScanDirectory(const char * dir, const char * parent)
|
ScanDirectory(const char * dir, const char * parent, enum media_types type)
|
||||||
{
|
{
|
||||||
struct dirent **namelist;
|
struct dirent **namelist;
|
||||||
int n, i;
|
int n, i, startID = 0;
|
||||||
char parent_id[PATH_MAX];
|
char parent_id[PATH_MAX];
|
||||||
char full_path[PATH_MAX];
|
char full_path[PATH_MAX];
|
||||||
char * name;
|
char * name = NULL;
|
||||||
#if USE_FORK
|
|
||||||
pid_t newpid;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( !parent )
|
|
||||||
{
|
|
||||||
if( create_database() != 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error creating database!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#if USE_FORK
|
|
||||||
newpid = fork();
|
|
||||||
if( newpid )
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
setlocale(LC_COLLATE, "");
|
setlocale(LC_COLLATE, "");
|
||||||
if( chdir(dir) != 0 )
|
if( chdir(dir) != 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("\nScanning %s\n", dir);
|
printf("\nScanning %s\n", dir);
|
||||||
n = scandir(".", &namelist, filter_media, alphasort);
|
switch( type )
|
||||||
|
{
|
||||||
|
case ALL_MEDIA:
|
||||||
|
n = scandir(".", &namelist, filter_media, alphasort);
|
||||||
|
break;
|
||||||
|
case AUDIO_ONLY:
|
||||||
|
n = scandir(".", &namelist, filter_audio, alphasort);
|
||||||
|
break;
|
||||||
|
case VIDEO_ONLY:
|
||||||
|
n = scandir(".", &namelist, filter_video, alphasort);
|
||||||
|
break;
|
||||||
|
case IMAGES_ONLY:
|
||||||
|
n = scandir(".", &namelist, filter_images, alphasort);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
fprintf(stderr, "Error scanning %s [scandir]\n", dir);
|
fprintf(stderr, "Error scanning %s [scandir]\n", dir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sql = sqlite3_mprintf("SELECT OBJECT_ID, max(ID) from OBJECTS where PARENT_ID = '%s$%X'", rootParent, parentID);
|
||||||
|
ret = sql_get_table(db, sql, &result, 0, &cols);
|
||||||
|
if( result[2] && (sscanf(rindex(result[2], '$')+1, "%X", &objectID) == 1) )
|
||||||
|
{
|
||||||
|
objectID++;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if( !parent )
|
||||||
|
startID = get_next_available_id("OBJECTS", BROWSEDIR_ID);
|
||||||
|
|
||||||
for (i=0; i < n; i++) {
|
for (i=0; i < n; i++) {
|
||||||
name = NULL;
|
|
||||||
sprintf(full_path, "%s/%s", dir, namelist[i]->d_name);
|
sprintf(full_path, "%s/%s", dir, namelist[i]->d_name);
|
||||||
if( index(namelist[i]->d_name, '&') )
|
if( index(namelist[i]->d_name, '&') )
|
||||||
{
|
{
|
||||||
@ -612,16 +646,19 @@ ScanDirectory(const char * dir, const char * parent)
|
|||||||
}
|
}
|
||||||
if( namelist[i]->d_type == DT_DIR )
|
if( namelist[i]->d_type == DT_DIR )
|
||||||
{
|
{
|
||||||
insert_directory(name?name:namelist[i]->d_name, full_path, BROWSEDIR_ID, (parent ? parent:""), i);
|
insert_directory(name?name:namelist[i]->d_name, full_path, BROWSEDIR_ID, (parent ? parent:""), i+startID);
|
||||||
sprintf(parent_id, "%s$%X", (parent ? parent:""), i);
|
sprintf(parent_id, "%s$%X", (parent ? parent:""), i+startID);
|
||||||
ScanDirectory(full_path, parent_id);
|
ScanDirectory(full_path, parent_id, type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
insert_file(name?name:namelist[i]->d_name, full_path, (parent ? parent:""), i);
|
insert_file(name?name:namelist[i]->d_name, full_path, (parent ? parent:""), i+startID);
|
||||||
}
|
}
|
||||||
if( name )
|
if( name )
|
||||||
|
{
|
||||||
free(name);
|
free(name);
|
||||||
|
name = NULL;
|
||||||
|
}
|
||||||
free(namelist[i]);
|
free(namelist[i]);
|
||||||
}
|
}
|
||||||
free(namelist);
|
free(namelist);
|
||||||
@ -632,8 +669,5 @@ ScanDirectory(const char * dir, const char * parent)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Scanning \"%s\" finished!\n", dir);
|
printf("Scanning \"%s\" finished!\n", dir);
|
||||||
#if USE_FORK
|
|
||||||
_exit(0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
#define VIDEO_DIR_ID "2$21"
|
#define VIDEO_DIR_ID "2$21"
|
||||||
#define IMAGE_DIR_ID "3$22"
|
#define IMAGE_DIR_ID "3$22"
|
||||||
|
|
||||||
|
int
|
||||||
|
CreateDatabase(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
ScanDirectory(const char * dir, const char * parent);
|
ScanDirectory(const char * dir, const char * parent, enum media_types type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,6 +26,7 @@ int logpackets = 0;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct runtime_vars_s runtime_vars;
|
||||||
int runtime_flags = 0;
|
int runtime_flags = 0;
|
||||||
|
|
||||||
const char * pidfilename = "/var/run/minidlna.pid";
|
const char * pidfilename = "/var/run/minidlna.pid";
|
||||||
@ -44,5 +45,5 @@ struct lan_addr_s lan_addr[MAX_LAN_ADDR];
|
|||||||
|
|
||||||
/* UPnP-A/V [DLNA] */
|
/* UPnP-A/V [DLNA] */
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
char media_dir[MEDIADIR_MAX_LEN];
|
struct media_dir_s * media_dirs = NULL;
|
||||||
char friendly_name[FRIENDLYNAME_MAX_LEN];
|
char friendly_name[FRIENDLYNAME_MAX_LEN];
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
/* statup time */
|
/* statup time */
|
||||||
extern time_t startup_time;
|
extern time_t startup_time;
|
||||||
|
|
||||||
|
extern struct runtime_vars_s runtime_vars;
|
||||||
/* runtime boolean flags */
|
/* runtime boolean flags */
|
||||||
extern int runtime_flags;
|
extern int runtime_flags;
|
||||||
#define LOGPACKETSMASK 0x0001
|
#define LOGPACKETSMASK 0x0001
|
||||||
@ -81,7 +82,7 @@ extern struct lan_addr_s lan_addr[];
|
|||||||
/* UPnP-A/V [DLNA] */
|
/* UPnP-A/V [DLNA] */
|
||||||
extern sqlite3 *db;
|
extern sqlite3 *db;
|
||||||
#define MEDIADIR_MAX_LEN (256)
|
#define MEDIADIR_MAX_LEN (256)
|
||||||
extern char media_dir[];
|
extern struct media_dir_s * media_dirs;
|
||||||
#define FRIENDLYNAME_MAX_LEN (64)
|
#define FRIENDLYNAME_MAX_LEN (64)
|
||||||
extern char friendly_name[];
|
extern char friendly_name[];
|
||||||
|
|
||||||
|
10
upnphttp.c
10
upnphttp.c
@ -1178,6 +1178,9 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
int sendfh;
|
int sendfh;
|
||||||
#if USE_FORK
|
#if USE_FORK
|
||||||
pid_t newpid = 0;
|
pid_t newpid = 0;
|
||||||
|
newpid = fork();
|
||||||
|
if( newpid )
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(header, 0, 1500);
|
memset(header, 0, 1500);
|
||||||
@ -1192,15 +1195,10 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
sqlite3_free_table(result);
|
sqlite3_free_table(result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if USE_FORK
|
|
||||||
newpid = fork();
|
|
||||||
if( newpid )
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
path = result[3];
|
path = result[3];
|
||||||
mime = result[4];
|
mime = result[4];
|
||||||
dlna = result[5];
|
dlna = result[5];
|
||||||
|
|
||||||
printf("Serving DetailID: %s [%s]\n", object, path);
|
printf("Serving DetailID: %s [%s]\n", object, path);
|
||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING )
|
if( h->reqflags & FLAG_XFERSTREAMING )
|
||||||
|
18
upnpsoap.c
18
upnpsoap.c
@ -270,10 +270,10 @@ static int callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
}
|
}
|
||||||
if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) {
|
if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) {
|
||||||
sprintf(str_buf, "<upnp:albumArtURI %s"
|
sprintf(str_buf, "<upnp:albumArtURI %s"
|
||||||
">http://%s:5555/AlbumArt/%s.jpg</upnp:albumArtURI>",
|
">http://%s:%d/AlbumArt/%s.jpg</upnp:albumArtURI>",
|
||||||
(!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI@dlna:profileID")) ?
|
(!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI@dlna:profileID")) ?
|
||||||
"dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\"" : "",
|
"dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\"" : "",
|
||||||
lan_addr[0].str, album_art);
|
lan_addr[0].str, runtime_vars.port, album_art);
|
||||||
strcat(passed_args->resp, str_buf);
|
strcat(passed_args->resp, str_buf);
|
||||||
}
|
}
|
||||||
if( !passed_args->filter || strstr(passed_args->filter, "res") ) {
|
if( !passed_args->filter || strstr(passed_args->filter, "res") ) {
|
||||||
@ -303,26 +303,26 @@ static int callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
strcat(passed_args->resp, str_buf);
|
strcat(passed_args->resp, str_buf);
|
||||||
}
|
}
|
||||||
sprintf(str_buf, "protocolInfo=\"http-get:*:%s:%s\">"
|
sprintf(str_buf, "protocolInfo=\"http-get:*:%s:%s\">"
|
||||||
"http://%s:5555/MediaItems/%s.dat"
|
"http://%s:%d/MediaItems/%s.dat"
|
||||||
"</res>",
|
"</res>",
|
||||||
mime, dlna_buf, lan_addr[0].str, detailID);
|
mime, dlna_buf, lan_addr[0].str, runtime_vars.port, detailID);
|
||||||
#if 0 //JPEG_RESIZE
|
#if 0 //JPEG_RESIZE
|
||||||
if( dlna_pn && (strncmp(dlna_pn, "JPEG_LRG", 8) == 0) ) {
|
if( dlna_pn && (strncmp(dlna_pn, "JPEG_LRG", 8) == 0) ) {
|
||||||
strcat(passed_args->resp, str_buf);
|
strcat(passed_args->resp, str_buf);
|
||||||
sprintf(str_buf, "<res "
|
sprintf(str_buf, "<res "
|
||||||
"protocolInfo=\"http-get:*:%s:%s\">"
|
"protocolInfo=\"http-get:*:%s:%s\">"
|
||||||
"http://%s:5555/Resized/%s"
|
"http://%s:%d/Resized/%s"
|
||||||
"</res>",
|
"</res>",
|
||||||
mime, "DLNA.ORG_PN=JPEG_SM", lan_addr[0].str, id);
|
mime, "DLNA.ORG_PN=JPEG_SM", lan_addr[0].str, runtime_vars.port, id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if( tn && atoi(tn) && dlna_pn ) {
|
if( tn && atoi(tn) && dlna_pn ) {
|
||||||
strcat(passed_args->resp, str_buf);
|
strcat(passed_args->resp, str_buf);
|
||||||
strcat(passed_args->resp, "<res ");
|
strcat(passed_args->resp, "<res ");
|
||||||
sprintf(str_buf, "protocolInfo=\"http-get:*:%s:%s\">"
|
sprintf(str_buf, "protocolInfo=\"http-get:*:%s:%s\">"
|
||||||
"http://%s:5555/Thumbnails/%s.dat"
|
"http://%s:%d/Thumbnails/%s.dat"
|
||||||
"</res>",
|
"</res>",
|
||||||
mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str, detailID);
|
mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str, runtime_vars.port, detailID);
|
||||||
}
|
}
|
||||||
strcat(passed_args->resp, str_buf);
|
strcat(passed_args->resp, str_buf);
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ static int callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
}
|
}
|
||||||
if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) {
|
if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) {
|
||||||
sprintf(str_buf, "<upnp:albumArtURI dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\""
|
sprintf(str_buf, "<upnp:albumArtURI dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\""
|
||||||
">http://%s:5555/AlbumArt/%s.jpg</upnp:albumArtURI>", lan_addr[0].str, album_art);
|
">http://%s:%d/AlbumArt/%s.jpg</upnp:albumArtURI>", lan_addr[0].str, runtime_vars.port, album_art);
|
||||||
strcat(passed_args->resp, str_buf);
|
strcat(passed_args->resp, str_buf);
|
||||||
}
|
}
|
||||||
sprintf(str_buf, "</container>");
|
sprintf(str_buf, "</container>");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user