* Add support for limiting a media dir to multiple media types.

This commit is contained in:
Justin Maggard 2012-10-03 07:26:00 +00:00
parent fdcdd9ded8
commit 584258c1f8
8 changed files with 172 additions and 108 deletions

1
NEWS
View File

@ -4,6 +4,7 @@
- Switch to autoconf from our handcrafted genconfig.sh. - Switch to autoconf from our handcrafted genconfig.sh.
- Add configuration option for UUID. - Add configuration option for UUID.
- Add configuration option to specify the user to run as. - Add configuration option to specify the user to run as.
- Add support for limiting a media dir to multiple media types.
1.0.25 - Released 13-July-2012 1.0.25 - Released 13-July-2012
-------------------------------- --------------------------------

View File

@ -290,7 +290,7 @@ inotify_insert_file(char * name, const char * path)
char * id = NULL; char * id = NULL;
int depth = 1; int depth = 1;
int ts; int ts;
enum media_types type = ALL_MEDIA; media_types types = ALL_MEDIA;
struct media_dir_s * media_path = media_dirs; struct media_dir_s * media_path = media_dirs;
struct stat st; struct stat st;
@ -305,12 +305,12 @@ inotify_insert_file(char * name, const char * path)
{ {
if( strncmp(path, media_path->path, strlen(media_path->path)) == 0 ) if( strncmp(path, media_path->path, strlen(media_path->path)) == 0 )
{ {
type = media_path->type; types = media_path->types;
break; break;
} }
media_path = media_path->next; media_path = media_path->next;
} }
switch( type ) switch( types )
{ {
case ALL_MEDIA: case ALL_MEDIA:
if( !is_image(path) && if( !is_image(path) &&
@ -319,16 +319,32 @@ inotify_insert_file(char * name, const char * path)
!is_playlist(path) ) !is_playlist(path) )
return -1; return -1;
break; break;
case AUDIO_ONLY: case TYPE_AUDIO:
if( !is_audio(path) && if( !is_audio(path) &&
!is_playlist(path) ) !is_playlist(path) )
return -1; return -1;
break; break;
case VIDEO_ONLY: case TYPE_AUDIO|TYPE_VIDEO:
if( !is_audio(path) &&
!is_video(path) &&
!is_playlist(path) )
break;
case TYPE_AUDIO|TYPE_IMAGES:
if( !is_image(path) &&
!is_audio(path) &&
!is_playlist(path) )
return -1;
break;
case TYPE_VIDEO:
if( !is_video(path) ) if( !is_video(path) )
return -1; return -1;
break; break;
case IMAGES_ONLY: case TYPE_VIDEO|TYPE_IMAGES:
if( !is_image(path) &&
!is_video(path) )
return -1;
break;
case TYPE_IMAGES:
if( !is_image(path) ) if( !is_image(path) )
return -1; return -1;
break; break;
@ -426,8 +442,8 @@ inotify_insert_directory(int fd, char *name, const char * path)
char path_buf[PATH_MAX]; char path_buf[PATH_MAX];
int wd; int wd;
enum file_types type = TYPE_UNKNOWN; enum file_types type = TYPE_UNKNOWN;
enum media_types dir_type = ALL_MEDIA; media_types dir_types = ALL_MEDIA;
struct media_dir_s * media_path; struct media_dir_s* media_path;
struct stat st; struct stat st;
if( access(path, R_OK|X_OK) != 0 ) if( access(path, R_OK|X_OK) != 0 )
@ -465,7 +481,7 @@ inotify_insert_directory(int fd, char *name, const char * path)
{ {
if( strncmp(path, media_path->path, strlen(media_path->path)) == 0 ) if( strncmp(path, media_path->path, strlen(media_path->path)) == 0 )
{ {
dir_type = media_path->type; dir_types = media_path->types;
break; break;
} }
media_path = media_path->next; media_path = media_path->next;
@ -489,7 +505,7 @@ inotify_insert_directory(int fd, char *name, const char * path)
case DT_REG: case DT_REG:
case DT_LNK: case DT_LNK:
case DT_UNKNOWN: case DT_UNKNOWN:
type = resolve_unknown_type(path_buf, dir_type); type = resolve_unknown_type(path_buf, dir_types);
default: default:
break; break;
} }

View File

@ -496,12 +496,13 @@ init(int argc, char * * argv)
const char * optionsfile = "/etc/minidlna.conf"; const char * optionsfile = "/etc/minidlna.conf";
char mac_str[13]; char mac_str[13];
char *string, *word; char *string, *word;
enum media_types type;
char *path; char *path;
char buf[PATH_MAX]; char buf[PATH_MAX];
char ip_addr[INET_ADDRSTRLEN + 3] = {'\0'}; char ip_addr[INET_ADDRSTRLEN + 3] = {'\0'};
char log_str[75] = "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn"; char log_str[75] = "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn";
char *log_level = NULL; char *log_level = NULL;
struct media_dir_s *media_dir;
media_types types;
uid_t uid = -1; uid_t uid = -1;
/* first check if "-f" option is used */ /* first check if "-f" option is used */
@ -598,30 +599,39 @@ init(int argc, char * * argv)
strncpyt(friendly_name, ary_options[i].value, FRIENDLYNAME_MAX_LEN); strncpyt(friendly_name, ary_options[i].value, FRIENDLYNAME_MAX_LEN);
break; break;
case UPNPMEDIADIR: case UPNPMEDIADIR:
type = ALL_MEDIA; types = ALL_MEDIA;
path = ary_options[i].value; path = ary_options[i].value;
if( *path && (path[1] == ',') && (access(path, F_OK) != 0) ) word = strchr(path, ',');
if( word && (access(path, F_OK) != 0) )
{ {
switch( *path ) types = 0;
while( *path )
{ {
case 'A': if( *path == 'A' || *path == 'a' )
case 'a': {
type = AUDIO_ONLY; types |= TYPE_AUDIO;
break; }
case 'V': else if( *path == 'V' || *path == 'v' )
case 'v': {
type = VIDEO_ONLY; types |= TYPE_VIDEO;
break; }
case 'P': else if( *path == 'P' || *path == 'p' )
case 'p': {
type = IMAGES_ONLY; types |= TYPE_IMAGES;
break; }
default: else if( *path == ',' )
DPRINTF(E_FATAL, L_GENERAL, "Media directory entry not understood [%s]\n", {
ary_options[i].value); path++;
break; break;
}
else
{
DPRINTF(E_FATAL, L_GENERAL, "Media directory entry not understood [%s]\n",
ary_options[i].value);
break;
}
path++;
} }
path += 2;
} }
path = realpath(path, buf); path = realpath(path, buf);
if( !path || access(path, F_OK) != 0 ) if( !path || access(path, F_OK) != 0 )
@ -630,19 +640,19 @@ init(int argc, char * * argv)
ary_options[i].value, strerror(errno)); ary_options[i].value, strerror(errno));
break; break;
} }
struct media_dir_s * this_dir = calloc(1, sizeof(struct media_dir_s)); media_dir = calloc(1, sizeof(struct media_dir_s));
this_dir->path = strdup(path); media_dir->path = strdup(path);
this_dir->type = type; media_dir->types = types;
if( !media_dirs ) if( !media_dirs )
{ {
media_dirs = this_dir; media_dirs = media_dir;
} }
else else
{ {
struct media_dir_s * all_dirs = media_dirs; struct media_dir_s * all_dirs = media_dirs;
while( all_dirs->next ) while( all_dirs->next )
all_dirs = all_dirs->next; all_dirs = all_dirs->next;
all_dirs->next = this_dir; all_dirs->next = media_dir;
} }
break; break;
case UPNPALBUMART_NAMES: case UPNPALBUMART_NAMES:

View File

@ -8,12 +8,13 @@ port=8200
#user=jmaggard #user=jmaggard
# set this to the directory you want scanned. # set this to the directory you want scanned.
# * if have multiple directories, you can have multiple media_dir= lines # * if you want multiple directories, you can have multiple media_dir= lines
# * if you want to restrict a media_dir to a specific content type, you # * if you want to restrict a media_dir to specific content types, you
# can prepend the type, followed by a comma, to the directory: # can prepend the types, followed by a comma, to the directory:
# + "A" for audio (eg. media_dir=A,/home/jmaggard/Music) # + "A" for audio (eg. media_dir=A,/home/jmaggard/Music)
# + "V" for video (eg. media_dir=V,/home/jmaggard/Videos) # + "V" for video (eg. media_dir=V,/home/jmaggard/Videos)
# + "P" for images (eg. media_dir=P,/home/jmaggard/Pictures) # + "P" for images (eg. media_dir=P,/home/jmaggard/Pictures)
# + "PV" for pictures and video (eg. media_dir=AV,/home/jmaggard/digital_camera)
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

View File

@ -53,13 +53,12 @@ struct string_s {
int size; int size;
}; };
enum media_types { typedef uint8_t media_types;
ALL_MEDIA, #define NO_MEDIA 0x00
AUDIO_ONLY, #define TYPE_AUDIO 0x01
VIDEO_ONLY, #define TYPE_VIDEO 0x02
IMAGES_ONLY, #define TYPE_IMAGES 0x04
NO_MEDIA #define ALL_MEDIA TYPE_AUDIO|TYPE_VIDEO|TYPE_IMAGES
};
enum file_types { enum file_types {
TYPE_UNKNOWN, TYPE_UNKNOWN,
@ -90,15 +89,15 @@ enum client_types {
}; };
struct media_dir_s { struct media_dir_s {
char * path; /* Base path */ char *path; /* base path */
enum media_types type; /* type of files to scan */ media_types types; /* types of files to scan */
struct media_dir_s * next; struct media_dir_s *next;
}; };
struct album_art_name_s { struct album_art_name_s {
char * name; /* Base path */ char *name; /* base path */
uint8_t wildcard; uint8_t wildcard;
struct album_art_name_s * next; struct album_art_name_s *next;
}; };
struct client_cache_s { struct client_cache_s {

141
scanner.c
View File

@ -594,62 +594,90 @@ sql_failed:
return (ret != SQLITE_OK); return (ret != SQLITE_OK);
} }
int static int
filter_audio(scan_filter *d) filter_type(scan_filter *d)
{ {
return ( (*d->d_name != '.') && return ( (*d->d_name != '.') &&
((d->d_type == DT_DIR) || ((d->d_type == DT_DIR) ||
(d->d_type == DT_LNK) || (d->d_type == DT_LNK) ||
(d->d_type == DT_UNKNOWN) || (d->d_type == DT_UNKNOWN))
((d->d_type == DT_REG) && );
(is_audio(d->d_name) ||
is_playlist(d->d_name)
)
) ));
} }
int static int
filter_video(scan_filter *d) filter_a(scan_filter *d)
{ {
return ( (*d->d_name != '.') && return ( filter_type(d) ||
((d->d_type == DT_DIR) || ((d->d_type == DT_REG) &&
(d->d_type == DT_LNK) || (is_audio(d->d_name) ||
(d->d_type == DT_UNKNOWN) || is_playlist(d->d_name))
((d->d_type == DT_REG) &&
is_video(d->d_name) )
) ); ) );
} }
int static int
filter_images(scan_filter *d) filter_av(scan_filter *d)
{ {
return ( (*d->d_name != '.') && return ( filter_type(d) ||
((d->d_type == DT_DIR) || ((d->d_type == DT_REG) &&
(d->d_type == DT_LNK) || (is_audio(d->d_name) ||
(d->d_type == DT_UNKNOWN) || is_video(d->d_name) ||
((d->d_type == DT_REG) && is_playlist(d->d_name)))
is_image(d->d_name) ) );
) );
} }
int static int
filter_media(scan_filter *d) filter_ap(scan_filter *d)
{ {
return ( (*d->d_name != '.') && return ( filter_type(d) ||
((d->d_type == DT_DIR) || ((d->d_type == DT_REG) &&
(d->d_type == DT_LNK) || (is_audio(d->d_name) ||
(d->d_type == DT_UNKNOWN) || is_image(d->d_name) ||
((d->d_type == DT_REG) && is_playlist(d->d_name)))
(is_image(d->d_name) || );
is_audio(d->d_name) || }
is_video(d->d_name) ||
is_playlist(d->d_name) static int
) filter_v(scan_filter *d)
) )); {
return ( filter_type(d) ||
(d->d_type == DT_REG &&
is_video(d->d_name))
);
}
static int
filter_vp(scan_filter *d)
{
return ( filter_type(d) ||
((d->d_type == DT_REG) &&
(is_video(d->d_name) ||
is_image(d->d_name)))
);
}
static int
filter_p(scan_filter *d)
{
return ( filter_type(d) ||
(d->d_type == DT_REG &&
is_image(d->d_name))
);
}
static int
filter_avp(scan_filter *d)
{
return ( filter_type(d) ||
((d->d_type == DT_REG) &&
(is_audio(d->d_name) ||
is_image(d->d_name) ||
is_video(d->d_name) ||
is_playlist(d->d_name)))
);
} }
void void
ScanDirectory(const char *dir, const char *parent, enum media_types dir_type) ScanDirectory(const char *dir, const char *parent, media_types dir_types)
{ {
struct dirent **namelist; struct dirent **namelist;
int i, n, startID=0; int i, n, startID=0;
@ -659,22 +687,29 @@ ScanDirectory(const char *dir, const char *parent, enum media_types dir_type)
static long long unsigned int fileno = 0; static long long unsigned int fileno = 0;
enum file_types type; enum file_types type;
setlocale(LC_COLLATE, "");
DPRINTF(parent?E_INFO:E_WARN, L_SCANNER, _("Scanning %s\n"), dir); DPRINTF(parent?E_INFO:E_WARN, L_SCANNER, _("Scanning %s\n"), dir);
switch( dir_type ) switch( dir_types )
{ {
case ALL_MEDIA: case ALL_MEDIA:
n = scandir(dir, &namelist, filter_media, alphasort); n = scandir(dir, &namelist, filter_avp, alphasort);
break; break;
case AUDIO_ONLY: case TYPE_AUDIO:
n = scandir(dir, &namelist, filter_audio, alphasort); n = scandir(dir, &namelist, filter_a, alphasort);
break; break;
case VIDEO_ONLY: case TYPE_AUDIO|TYPE_VIDEO:
n = scandir(dir, &namelist, filter_video, alphasort); n = scandir(dir, &namelist, filter_av, alphasort);
break; break;
case IMAGES_ONLY: case TYPE_AUDIO|TYPE_IMAGES:
n = scandir(dir, &namelist, filter_images, alphasort); n = scandir(dir, &namelist, filter_ap, alphasort);
break;
case TYPE_VIDEO:
n = scandir(dir, &namelist, filter_v, alphasort);
break;
case TYPE_VIDEO|TYPE_IMAGES:
n = scandir(dir, &namelist, filter_vp, alphasort);
break;
case TYPE_IMAGES:
n = scandir(dir, &namelist, filter_p, alphasort);
break; break;
default: default:
n = -1; n = -1;
@ -709,13 +744,13 @@ ScanDirectory(const char *dir, const char *parent, enum media_types dir_type)
} }
else else
{ {
type = resolve_unknown_type(full_path, dir_type); type = resolve_unknown_type(full_path, dir_types);
} }
if( (type == TYPE_DIR) && (access(full_path, R_OK|X_OK) == 0) ) if( (type == TYPE_DIR) && (access(full_path, R_OK|X_OK) == 0) )
{ {
insert_directory(name, full_path, BROWSEDIR_ID, (parent ? parent:""), i+startID); insert_directory(name, full_path, BROWSEDIR_ID, (parent ? parent:""), i+startID);
sprintf(parent_id, "%s$%X", (parent ? parent:""), i+startID); sprintf(parent_id, "%s$%X", (parent ? parent:""), i+startID);
ScanDirectory(full_path, parent_id, dir_type); ScanDirectory(full_path, parent_id, dir_types);
} }
else if( type == TYPE_FILE && (access(full_path, R_OK) == 0) ) else if( type == TYPE_FILE && (access(full_path, R_OK) == 0) )
{ {
@ -746,13 +781,15 @@ start_scanner()
if( flag ) if( flag )
fclose(flag); fclose(flag);
#endif #endif
setlocale(LC_COLLATE, "");
av_register_all(); av_register_all();
av_log_set_level(AV_LOG_PANIC); av_log_set_level(AV_LOG_PANIC);
while( media_path ) while( media_path )
{ {
strncpyt(name, media_path->path, sizeof(name)); strncpyt(name, media_path->path, sizeof(name));
GetFolderMetadata(basename(name), media_path->path, NULL, NULL, 0); GetFolderMetadata(basename(name), media_path->path, NULL, NULL, 0);
ScanDirectory(media_path->path, NULL, media_path->type); ScanDirectory(media_path->path, NULL, media_path->types);
media_path = media_path->next; media_path = media_path->next;
} }
#ifdef READYNAS #ifdef READYNAS

View File

@ -358,7 +358,7 @@ is_album_art(const char * name)
} }
int int
resolve_unknown_type(const char * path, enum media_types dir_type) resolve_unknown_type(const char * path, media_types dir_type)
{ {
struct stat entry; struct stat entry;
unsigned char type = TYPE_UNKNOWN; unsigned char type = TYPE_UNKNOWN;
@ -397,16 +397,16 @@ resolve_unknown_type(const char * path, enum media_types dir_type)
is_playlist(path) ) is_playlist(path) )
type = TYPE_FILE; type = TYPE_FILE;
break; break;
case AUDIO_ONLY: case TYPE_AUDIO:
if( is_audio(path) || if( is_audio(path) ||
is_playlist(path) ) is_playlist(path) )
type = TYPE_FILE; type = TYPE_FILE;
break; break;
case VIDEO_ONLY: case TYPE_VIDEO:
if( is_video(path) ) if( is_video(path) )
type = TYPE_FILE; type = TYPE_FILE;
break; break;
case IMAGES_ONLY: case TYPE_IMAGES:
if( is_image(path) ) if( is_image(path) )
type = TYPE_FILE; type = TYPE_FILE;
break; break;

View File

@ -78,6 +78,6 @@ int
is_album_art(const char * name); is_album_art(const char * name);
int int
resolve_unknown_type(const char * path, enum media_types dir_type); resolve_unknown_type(const char * path, media_types dir_type);
#endif #endif