* 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.
- Add configuration option for UUID.
- 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
--------------------------------

View File

@ -290,7 +290,7 @@ inotify_insert_file(char * name, const char * path)
char * id = NULL;
int depth = 1;
int ts;
enum media_types type = ALL_MEDIA;
media_types types = ALL_MEDIA;
struct media_dir_s * media_path = media_dirs;
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 )
{
type = media_path->type;
types = media_path->types;
break;
}
media_path = media_path->next;
}
switch( type )
switch( types )
{
case ALL_MEDIA:
if( !is_image(path) &&
@ -319,16 +319,32 @@ inotify_insert_file(char * name, const char * path)
!is_playlist(path) )
return -1;
break;
case AUDIO_ONLY:
case TYPE_AUDIO:
if( !is_audio(path) &&
!is_playlist(path) )
return -1;
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) )
return -1;
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) )
return -1;
break;
@ -426,8 +442,8 @@ inotify_insert_directory(int fd, char *name, const char * path)
char path_buf[PATH_MAX];
int wd;
enum file_types type = TYPE_UNKNOWN;
enum media_types dir_type = ALL_MEDIA;
struct media_dir_s * media_path;
media_types dir_types = ALL_MEDIA;
struct media_dir_s* media_path;
struct stat st;
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 )
{
dir_type = media_path->type;
dir_types = media_path->types;
break;
}
media_path = media_path->next;
@ -489,7 +505,7 @@ inotify_insert_directory(int fd, char *name, const char * path)
case DT_REG:
case DT_LNK:
case DT_UNKNOWN:
type = resolve_unknown_type(path_buf, dir_type);
type = resolve_unknown_type(path_buf, dir_types);
default:
break;
}

View File

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

View File

@ -8,12 +8,13 @@ port=8200
#user=jmaggard
# 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:
# * if you want multiple directories, you can have multiple media_dir= lines
# * if you want to restrict a media_dir to specific content types, you
# can prepend the types, 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)
# + "PV" for pictures and video (eg. media_dir=AV,/home/jmaggard/digital_camera)
media_dir=/opt
# 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;
};
enum media_types {
ALL_MEDIA,
AUDIO_ONLY,
VIDEO_ONLY,
IMAGES_ONLY,
NO_MEDIA
};
typedef uint8_t media_types;
#define NO_MEDIA 0x00
#define TYPE_AUDIO 0x01
#define TYPE_VIDEO 0x02
#define TYPE_IMAGES 0x04
#define ALL_MEDIA TYPE_AUDIO|TYPE_VIDEO|TYPE_IMAGES
enum file_types {
TYPE_UNKNOWN,
@ -90,15 +89,15 @@ enum client_types {
};
struct media_dir_s {
char * path; /* Base path */
enum media_types type; /* type of files to scan */
struct media_dir_s * next;
char *path; /* base path */
media_types types; /* types of files to scan */
struct media_dir_s *next;
};
struct album_art_name_s {
char * name; /* Base path */
char *name; /* base path */
uint8_t wildcard;
struct album_art_name_s * next;
struct album_art_name_s *next;
};
struct client_cache_s {

145
scanner.c
View File

@ -594,62 +594,90 @@ sql_failed:
return (ret != SQLITE_OK);
}
int
filter_audio(scan_filter *d)
static int
filter_type(scan_filter *d)
{
return ( (*d->d_name != '.') &&
((d->d_type == DT_DIR) ||
(d->d_type == DT_LNK) ||
(d->d_type == DT_UNKNOWN) ||
(d->d_type == DT_UNKNOWN))
);
}
static int
filter_a(scan_filter *d)
{
return ( filter_type(d) ||
((d->d_type == DT_REG) &&
(is_audio(d->d_name) ||
is_playlist(d->d_name)
)
) ));
}
int
filter_video(scan_filter *d)
{
return ( (*d->d_name != '.') &&
((d->d_type == DT_DIR) ||
(d->d_type == DT_LNK) ||
(d->d_type == DT_UNKNOWN) ||
((d->d_type == DT_REG) &&
is_video(d->d_name) )
is_playlist(d->d_name))
) );
}
int
filter_images(scan_filter *d)
static int
filter_av(scan_filter *d)
{
return ( (*d->d_name != '.') &&
((d->d_type == DT_DIR) ||
(d->d_type == DT_LNK) ||
(d->d_type == DT_UNKNOWN) ||
return ( filter_type(d) ||
((d->d_type == DT_REG) &&
is_image(d->d_name) )
) );
}
int
filter_media(scan_filter *d)
{
return ( (*d->d_name != '.') &&
((d->d_type == DT_DIR) ||
(d->d_type == DT_LNK) ||
(d->d_type == DT_UNKNOWN) ||
((d->d_type == DT_REG) &&
(is_image(d->d_name) ||
is_audio(d->d_name) ||
(is_audio(d->d_name) ||
is_video(d->d_name) ||
is_playlist(d->d_name)
)
) ));
is_playlist(d->d_name)))
);
}
static int
filter_ap(scan_filter *d)
{
return ( filter_type(d) ||
((d->d_type == DT_REG) &&
(is_audio(d->d_name) ||
is_image(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
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;
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;
enum file_types type;
setlocale(LC_COLLATE, "");
DPRINTF(parent?E_INFO:E_WARN, L_SCANNER, _("Scanning %s\n"), dir);
switch( dir_type )
switch( dir_types )
{
case ALL_MEDIA:
n = scandir(dir, &namelist, filter_media, alphasort);
n = scandir(dir, &namelist, filter_avp, alphasort);
break;
case AUDIO_ONLY:
n = scandir(dir, &namelist, filter_audio, alphasort);
case TYPE_AUDIO:
n = scandir(dir, &namelist, filter_a, alphasort);
break;
case VIDEO_ONLY:
n = scandir(dir, &namelist, filter_video, alphasort);
case TYPE_AUDIO|TYPE_VIDEO:
n = scandir(dir, &namelist, filter_av, alphasort);
break;
case IMAGES_ONLY:
n = scandir(dir, &namelist, filter_images, alphasort);
case TYPE_AUDIO|TYPE_IMAGES:
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;
default:
n = -1;
@ -709,13 +744,13 @@ ScanDirectory(const char *dir, const char *parent, enum media_types dir_type)
}
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) )
{
insert_directory(name, full_path, BROWSEDIR_ID, (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) )
{
@ -746,13 +781,15 @@ start_scanner()
if( flag )
fclose(flag);
#endif
setlocale(LC_COLLATE, "");
av_register_all();
av_log_set_level(AV_LOG_PANIC);
while( media_path )
{
strncpyt(name, media_path->path, sizeof(name));
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;
}
#ifdef READYNAS

View File

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

View File

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