AC_LMS_CHECK_PKG(GENERIC, [libavcodec libavformat], [], [GENERIC=false])
])
+AC_ARG_ENABLE([magic],
+ [AC_HELP_STRING([--disable-magic],
+ [Disable mime computation with libmagic. @<:@default=enable@:>@])],
+ [enable_magic=${enableval}], [enable_magic=yes])
+
+if test "$enable_magic" = "yes"; then
+ AC_CHECK_HEADERS([magic.h], [], [AC_MSG_ERROR([libmagic magic.h header file not found])])
+ AC_CHECK_LIB([magic], [magic_open], [AC_SUBST([LIBMAGIC], [-lmagic])],
+ [AC_MSG_ERROR([libmagic library or magic_open function not found])], [-lz])
+fi
+
# plugins declarations
AC_LMS_OPTIONAL_MODULE([dummy], true)
AC_LMS_OPTIONAL_MODULE([jpeg], true)
echo -e " * modules........: $MODS $UNUSED_MODS"
echo -e " * daemon.........: ${build_daemon}"
+echo -e " * use libmagic...: ${enable_magic}"
lightmediascanner_dlna.c
liblightmediascanner_la_LIBADD = -ldl @SQLITE3_LIBS@ @LTLIBICONV@
-liblightmediascanner_la_LDFLAGS = -version-info @version_info@
+liblightmediascanner_la_LDFLAGS = -version-info @version_info@ @LIBMAGIC@
*/
#include <dlfcn.h>
+#ifdef HAVE_MAGIC_H
+#include <magic.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_SLAVE_TIMEOUT 1000
#define DEFAULT_COMMIT_INTERVAL 100
+#ifdef HAVE_MAGIC_H
+static magic_t _magic_handle;
+
+static void
+_magic_handle_clean(void) {
+ magic_close(_magic_handle);
+}
+
+static int
+_magic_handle_setup(void) {
+ if (_magic_handle)
+ return 1;
+
+ _magic_handle = magic_open(MAGIC_MIME_TYPE | MAGIC_PRESERVE_ATIME);
+ if (!_magic_handle) {
+ fprintf(stderr, "ERROR: failed magic_open(): %s\n",
+ magic_error(_magic_handle));
+ return 0;
+ }
+
+ if (magic_load(_magic_handle, NULL) != 0) {
+ fprintf(stderr, "ERROR: failed magic_load() - %s\n",
+ magic_error(_magic_handle));
+ magic_close(_magic_handle);
+ _magic_handle = NULL;
+ return 0;
+ }
+
+ atexit(_magic_handle_clean);
+ return 1;
+}
+#endif
+
+int
+lms_mime_type_get_from_path(const char *path, struct lms_string_size *mime) {
+#ifdef HAVE_MAGIC_H
+ const char *s;
+ if (!path || !mime) return 0;
+ if (!_magic_handle_setup()) return 0;
+ s = magic_file(_magic_handle, path);
+ if (!s) return 0;
+ mime->str = (char *)s;
+ mime->len = strlen(s);
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+int
+lms_mime_type_get_from_fd(int fd, struct lms_string_size *mime) {
+#ifdef HAVE_MAGIC_H
+ const char *s;
+ if (fd < 0 || !mime) return 0;
+ if (!_magic_handle_setup()) return 0;
+ s = magic_descriptor(_magic_handle, fd);
+ if (!s) return 0;
+ mime->str = (char *)s;
+ mime->len = strlen(s);
+ return 1;
+#else
+ return 0;
+#endif
+}
+
static int
_parser_load(struct parser *p, const char *so_path)
{
* @author Leandro Dorileo <leandro.maciel.dorileo@intel.com>
*/
+#include "lightmediascanner.h"
#include <lightmediascanner_db.h>
+#include <lightmediascanner_private.h>
#include <stdio.h>
#include <math.h>
#define DLNA_VIDEO_FRAMERATE_RANGE(_min, _max) \
&(struct dlna_video_framerate_range) {.min = _min, .max = _max} \
+#ifdef HAVE_MAGIC_H
+
+#define LMS_DLNA_GET_PROFILE_PATH_FB(_info, _type, _dlna, _path) \
+ do { \
+ if ((_info)->dlna_mime.len == 0 && \
+ (_info)->dlna_profile.len == 0) { \
+ _dlna = lms_dlna_get_##_type##_profile(_info); \
+ if (_dlna) { \
+ (_info)->dlna_mime = *_dlna->dlna_mime; \
+ (_info)->dlna_profile = *_dlna->dlna_profile; \
+ } \
+ } \
+ if ((_info)->dlna_mime.len == 0) \
+ lms_mime_type_get_from_path(_path, &(_info)->dlna_mime); \
+ } while(0) \
+
+#define LMS_DLNA_GET_VIDEO_PROFILE_PATH_FB(_info, _dlna, _path) \
+ LMS_DLNA_GET_PROFILE_PATH_FB(_info, video, _dlna, _path) \
+
+#define LMS_DLNA_GET_AUDIO_PROFILE_PATH_FB(_info, _dlna, _path) \
+ LMS_DLNA_GET_PROFILE_PATH_FB(_info, audio, _dlna, _path) \
+
+#define LMS_DLNA_GET_IMAGE_PROFILE_PATH_FB(_info, _dlna, _path) \
+ LMS_DLNA_GET_PROFILE_PATH_FB(_info, image, _dlna, _path) \
+
+#define LMS_DLNA_GET_PROFILE_FD_FB(_info, _type, _dlna, _fd) \
+ do { \
+ if ((_info)->dlna_mime.len == 0 && \
+ (_info)->dlna_profile.len == 0) { \
+ _dlna = lms_dlna_get_##_type##_profile(_info); \
+ if (_dlna) { \
+ (_info)->dlna_mime = *_dlna->dlna_mime; \
+ (_info)->dlna_profile = *_dlna->dlna_profile; \
+ } \
+ } \
+ if ((_info)->dlna_mime.len == 0) \
+ lms_mime_type_get_from_fd(_fd, &(_info)->dlna_mime); \
+ } while(0) \
+
+#define LMS_DLNA_GET_VIDEO_PROFILE_FD_FB(_info, _dlna, _fd) \
+ LMS_DLNA_GET_PROFILE_FD_FB(_info, video, _dlna, _fd) \
+
+#define LMS_DLNA_GET_AUDIO_PROFILE_FD_FB(_info, _dlna, _fd) \
+ LMS_DLNA_GET_PROFILE_FD_FB(_info, audio, _dlna, _fd) \
+
+#define LMS_DLNA_GET_IMAGE_PROFILE_FD_FB(_info, _dlna, _fd) \
+ LMS_DLNA_GET_PROFILE_FD_FB(_info, image, _dlna, _fd) \
+
+#else
+
+#define LMS_DLNA_GET_VIDEO_PROFILE_PATH_FB(_info, _dlna, _path) \
+ do { _dlna = _dlna;} while(0) \
+
+#define LMS_DLNA_GET_AUDIO_PROFILE_PATH_FB(_info, _dlna, _path) \
+ do { _dlna = _dlna;} while(0) \
+
+#define LMS_DLNA_GET_IMAGE_PROFILE_PATH_FB(_info, _dlna, _path) \
+ do { _dlna = _dlna;} while(0) \
+
+#define LMS_DLNA_GET_VIDEO_PROFILE_FD_FB(_info, _dlna, _fd) \
+ do { _dlna = _dlna;} while(0) \
+
+#define LMS_DLNA_GET_AUDIO_PROFILE_FD_FB(_info, _dlna, _fd) \
+ do { _dlna = _dlna;} while(0) \
+
+#define LMS_DLNA_GET_IMAGE_PROFILE_FD_FB(_info, _dlna, _fd) \
+ do { _dlna = _dlna;} while(0) \
+
+#endif
+
struct dlna_bitrate {
const unsigned int min;
const unsigned int max;
const struct lms_dlna_image_rule *image_rule;
};
-const struct lms_dlna_video_profile *lms_dlna_get_video_profile(struct lms_video_info *info);
-const struct lms_dlna_audio_profile *lms_dlna_get_audio_profile(struct lms_audio_info *info);
-const struct lms_dlna_image_profile *lms_dlna_get_image_profile(struct lms_image_info *info);
+API const struct lms_dlna_video_profile *lms_dlna_get_video_profile(struct lms_video_info *info);
+API const struct lms_dlna_audio_profile *lms_dlna_get_audio_profile(struct lms_audio_info *info);
+API const struct lms_dlna_image_profile *lms_dlna_get_image_profile(struct lms_image_info *info);
#endif /* _LIGHTMEDIASCANNER_DLNA_H_ */
#include "lightmediascanner.h"
#include "lightmediascanner_plugin.h"
+#include "lightmediascanner_utils.h"
#include "lightmediascanner_charset_conv.h"
#include <sys/types.h>
#include <poll.h>
int lms_parsers_finish(lms_t *lms, sqlite3 *db) GNUC_NON_NULL(1, 2);
int lms_parsers_check_using(lms_t *lms, void **parser_match, struct lms_file_info *finfo) GNUC_NON_NULL(1, 2, 3);
int lms_parsers_run(lms_t *lms, sqlite3 *db, void **parser_match, struct lms_file_info *finfo) GNUC_NON_NULL(1, 2, 3, 4);
+API int lms_mime_type_get_from_path(const char *path, struct lms_string_size *mime) GNUC_NON_NULL(1, 2);
+API int lms_mime_type_get_from_fd(int fd, struct lms_string_size *mime) GNUC_NON_NULL(2);
#endif /* _LIGHTMEDIASCANNER_PRIVATE_H_ */
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <shared/util.h>
#include <endian.h>
unsigned int size;
unsigned long long hdrsize;
off_t pos_end, pos = 0;
+ const struct lms_dlna_video_profile *video_dlna;
+ const struct lms_dlna_audio_profile *audio_dlna;
fd = open(finfo->path, O_RDONLY);
if (fd < 0) {
audio_info.codec = s->base.codec;
}
+ LMS_DLNA_GET_AUDIO_PROFILE_FD_FB(&audio_info, audio_dlna, fd);
r = lms_db_audio_add(plugin->audio_db, &audio_info);
} else {
struct lms_video_info video_info = { };
video_info.length = info.length;
video_info.container = _container;
video_info.streams = (struct lms_stream *) info.streams;
+ LMS_DLNA_GET_VIDEO_PROFILE_FD_FB(&video_info, video_dlna, fd);
r = lms_db_video_add(plugin->video_db, &video_info);
}
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <stdio.h>
#include <stdlib.h>
char *str;
int len, r;
unsigned int i;
+ const struct lms_dlna_audio_profile *audio_dlna;
if (!FLAC__metadata_get_streaminfo(finfo->path, &si)) {
fprintf(stderr, "ERROR: cannot retrieve file %s STREAMINFO block\n",
#endif
info.id = finfo->id;
+ LMS_DLNA_GET_AUDIO_PROFILE_PATH_FB(&info, audio_dlna, finfo->path);
r = lms_db_audio_add(plugin->audio_db, &info);
free(info.title.str);
#include "libavutil/opt.h"
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <lightmediascanner_plugin.h>
#include <sys/types.h>
struct lms_video_info video_info = { };
struct lms_string_size container = { };
bool video = false;
+ const struct lms_dlna_video_profile *video_dlna;
+ const struct lms_dlna_audio_profile *audio_dlna;
if (finfo->parsed)
return 0;
video_info.container = container;
video_info.packet_size = packet_size;
+ LMS_DLNA_GET_VIDEO_PROFILE_PATH_FB(&video_info, video_dlna,
+ finfo->path);
ret = lms_db_video_add(plugin->video_db, &video_info);
} else {
audio_info.id = finfo->id;
audio_info.genre = info.genre;
audio_info.container = container;
+ LMS_DLNA_GET_AUDIO_PROFILE_PATH_FB(&audio_info, audio_dlna,
+ finfo->path);
ret = lms_db_audio_add(plugin->audio_db, &audio_info);
+
lms_string_size_strip_and_free(&audio_info.codec);
}
* http://id3.org/id3v2.3.0
*/
+#include <lightmediascanner_dlna.h>
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_db.h>
#include <lightmediascanner_charset_conv.h>
int r, fd;
long id3v2_offset;
off_t sync_offset = 0;
+ const struct lms_dlna_audio_profile *audio_dlna;
fd = open(finfo->path, O_RDONLY);
if (fd < 0) {
_parse_mpeg_header(fd, sync_offset, &audio_info, finfo->size);
audio_info.container = _container_mp3;
+ LMS_DLNA_GET_AUDIO_PROFILE_FD_FB(&audio_info, audio_dlna, fd);
r = lms_db_audio_add(plugin->audio_db, &audio_info);
done:
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_utils.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <shared/util.h>
#include <sys/types.h>
{
struct lms_image_info info = { };
int fd, type, len, r;
+ const struct lms_dlna_image_profile *image_dlna;
fd = open(finfo->path, O_RDONLY);
if (fd < 0) {
info.container = _container_jpeg;
info.id = finfo->id;
+ LMS_DLNA_GET_IMAGE_PROFILE_FD_FB(&info, image_dlna, fd);
r = lms_db_image_add(plugin->img_db, &info);
done:
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <mp4v2/mp4v2.h>
#include <string.h>
MP4FileHandle mp4_fh;
u_int32_t num_tracks, i;
const MP4Tags *tags;
+ const struct lms_dlna_video_profile *video_dlna;
+ const struct lms_dlna_audio_profile *audio_dlna;
mp4_fh = MP4Read(finfo->path);
if (mp4_fh == MP4_INVALID_FILE_HANDLE) {
audio_info.container = _get_container(mp4_fh);
audio_info.trackno = info.trackno;
+ LMS_DLNA_GET_AUDIO_PROFILE_PATH_FB(&audio_info, audio_dlna,
+ finfo->path);
r = lms_db_audio_add(plugin->audio_db, &audio_info);
} else {
video_info.id = finfo->id;
video_info.artist = info.artist;
video_info.container = _get_container(mp4_fh);
+ LMS_DLNA_GET_VIDEO_PROFILE_PATH_FB(&video_info, video_dlna,
+ finfo->path);
r = lms_db_video_add(plugin->video_db, &video_info);
}
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <lightmediascanner_utils.h>
#include <assert.h>
{
struct ogg_info info = { .type = LMS_STREAM_TYPE_UNKNOWN };
int r;
+ const struct lms_dlna_video_profile *video_dlna;
+ const struct lms_dlna_audio_profile *audio_dlna;
r = _parse_ogg(finfo->path, &info);
if (r != 0)
audio_info.sampling_rate = info.sampling_rate;
audio_info.bitrate = info.bitrate;
+ LMS_DLNA_GET_AUDIO_PROFILE_PATH_FB(&audio_info, audio_dlna,
+ finfo->path);
r = lms_db_audio_add(plugin->audio_db, &audio_info);
} else if (info.type == LMS_STREAM_TYPE_VIDEO) {
struct lms_video_info video_info = { };
video_info.artist = info.artist;
video_info.container = _container;
video_info.streams = (struct lms_stream *) info.streams;
+ LMS_DLNA_GET_VIDEO_PROFILE_PATH_FB(&video_info, video_dlna,
+ finfo->path);
r = lms_db_video_add(plugin->video_db, &video_info);
}
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_utils.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <sys/types.h>
#include <sys/stat.h>
{
struct lms_image_info info = { };
int fd, r;
+ const struct lms_dlna_image_profile *image_dlna;
fd = open(finfo->path, O_RDONLY);
if (fd < 0) {
info.id = finfo->id;
info.container = _container_png;
+ LMS_DLNA_GET_IMAGE_PROFILE_FD_FB(&info, image_dlna, fd);
r = lms_db_image_add(plugin->img_db, &info);
done:
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <sys/types.h>
#include <sys/stat.h>
char type[4];
uint32_t size;
bool has_cont = false, has_prop = false, has_mdpr = false;
+ const struct lms_dlna_video_profile *video_dlna;
+ const struct lms_dlna_audio_profile *audio_dlna;
fd = open(finfo->path, O_RDONLY);
if (fd < 0) {
audio_info.id = finfo->id;
audio_info.title = info.title;
audio_info.artist = info.artist;
+ LMS_DLNA_GET_AUDIO_PROFILE_FD_FB(&audio_info, audio_dlna, fd);
r = lms_db_audio_add(plugin->audio_db, &audio_info);
}
else {
video_info.id = finfo->id;
video_info.title = info.title;
video_info.artist = info.artist;
+ LMS_DLNA_GET_VIDEO_PROFILE_FD_FB(&video_info, video_dlna, fd);
r = lms_db_video_add(plugin->video_db, &video_info);
}
#include <lightmediascanner_plugin.h>
#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
#include <lightmediascanner_charset_conv.h>
#include <shared/util.h>
{
struct lms_audio_info info = { };
int r, fd;
+ const struct lms_dlna_audio_profile *audio_dlna;
fd = open(finfo->path, O_RDONLY);
if (fd < 0)
info.id = finfo->id;
+ LMS_DLNA_GET_AUDIO_PROFILE_FD_FB(&info, audio_dlna, fd);
r = lms_db_audio_add(plugin->audio_db, &info);
done: