* Add support for limiting a media dir to multiple media types.
This commit is contained in:
parent
fdcdd9ded8
commit
584258c1f8
1
NEWS
1
NEWS
@ -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
|
||||
--------------------------------
|
||||
|
36
inotify.c
36
inotify.c
@ -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;
|
||||
}
|
||||
|
62
minidlna.c
62
minidlna.c
@ -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;
|
||||
break;
|
||||
case 'V':
|
||||
case 'v':
|
||||
type = VIDEO_ONLY;
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
type = IMAGES_ONLY;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(E_FATAL, L_GENERAL, "Media directory entry not understood [%s]\n",
|
||||
ary_options[i].value);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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:
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
141
scanner.c
141
scanner.c
@ -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_REG) &&
|
||||
(is_audio(d->d_name) ||
|
||||
is_playlist(d->d_name)
|
||||
)
|
||||
) ));
|
||||
(d->d_type == DT_UNKNOWN))
|
||||
);
|
||||
}
|
||||
|
||||
int
|
||||
filter_video(scan_filter *d)
|
||||
static int
|
||||
filter_a(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) )
|
||||
return ( filter_type(d) ||
|
||||
((d->d_type == DT_REG) &&
|
||||
(is_audio(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) ||
|
||||
((d->d_type == DT_REG) &&
|
||||
is_image(d->d_name) )
|
||||
) );
|
||||
return ( filter_type(d) ||
|
||||
((d->d_type == DT_REG) &&
|
||||
(is_audio(d->d_name) ||
|
||||
is_video(d->d_name) ||
|
||||
is_playlist(d->d_name)))
|
||||
);
|
||||
}
|
||||
|
||||
int
|
||||
filter_media(scan_filter *d)
|
||||
static int
|
||||
filter_ap(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_video(d->d_name) ||
|
||||
is_playlist(d->d_name)
|
||||
)
|
||||
) ));
|
||||
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
|
||||
|
8
utils.c
8
utils.c
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user