diff -u ushare-1.1a/debian/changelog ushare-1.1a/debian/changelog --- ushare-1.1a/debian/changelog +++ ushare-1.1a/debian/changelog @@ -1,3 +1,10 @@ +ushare (1.1a-0ubuntu3) intrepid; urgency=low + + * Apply NeToU patch by David Brown + Fixes music and multiple directory serving + + -- Nullack Sat, 20 Sep 2008 18:38:04 +1000 + ushare (1.1a-0ubuntu2) intrepid; urgency=low * Rebuild for the ffmpeg -> ffmpeg-free transition (LP: #245571). only in patch2: unchanged: --- ushare-1.1a.orig/ChangeLog +++ ushare-1.1a/ChangeLog @@ -1,3 +1,17 @@ +2008-05-10 David Brown + + * Additional Xbox 360 support and bug fixes + music files can now be viewed properly through the 360 + dashboard (still no metadata). Multiple content directories + will also work correctly on the 360 now. + +2007-12-16 Alexis Saettler + + * added support for File Alteration Monitor, + to monitor files changes automaticaly and rebuild + metadata file list. Works with gamin too. + + 2007-12-09 Benjamin Zores * new public release (Version 1.1a). only in patch2: unchanged: --- ushare-1.1a.orig/configure +++ ushare-1.1a/configure @@ -30,12 +30,16 @@ echo " --prefix=PREFIX install in PREFIX [$PREFIX]" echo " --bindir=DIR install binaries in DIR [PREFIX/bin]" echo " --sysconfdir=DIR configuration files DIR [PREFIX/etc]" - echo " --localedir=DIR use locales from DIR [PREFIX/share/locale]" + echo " --datadir=DIR arch-independent data DIR [PREFIX/share]" + echo " --localedir=DIR use locales from DIR [DATADIR/locale]" + echo " --mandir=DIR man documentation DIR [DATADIR/man]" echo "" echo "Extended options:" echo " --enable-dlna enable DLNA support through libldna" echo " --disable-dlna disable DLNA support" echo " --disable-nls do not use Native Language Support" + echo " --enable-fam enable File Alteration Monitor support" + echo " --disable-fam disable File Alteration Monitor support" echo "" echo "Search paths:" echo " --with-libupnp-dir=DIR check for libupnp installed in DIR" @@ -292,8 +296,11 @@ PREFIX="/usr/local" bindir='${PREFIX}/bin' sysconfdir='${PREFIX}/etc' -localedir='${PREFIX}/share/locale' +datadir='${PREFIX}/share' +localedir='${datadir}/locale' +mandir='${datadir}/man' dlna="no" +fam="no" nls="yes" cc="gcc" make="make" @@ -306,7 +313,7 @@ installstrip="-s" cross_compile="no" INSTALL="/usr/bin/install -c" -VERSION="1.1a" +VERSION="1.1a-NeToU" system_name=`uname -s 2>&1` ################################################# @@ -408,8 +415,12 @@ ;; --sysconfdir=*) sysconfdir="$optval"; ;; + --datadir=*) datadir="$optval"; + ;; --localedir=*) localedir="$optval"; ;; + --mandir=*) mandir="$optval"; + ;; --with-libupnp-dir=*) libupnpdir="$optval"; ;; --with-libdlna-dir=*) libdlnadir="$optval"; @@ -420,6 +431,10 @@ ;; --disable-dlna) dlna="no" ;; + --enable-fam) fam="yes" + ;; + --disable-fam) fam="no" + ;; --enable-debug) debug="yes" ;; --disable-debug) debug="no" @@ -667,6 +682,16 @@ fi ################################################# +# check for libfam +################################################# +if test "$fam" = "yes"; then + echolog "Checking for libfam ..." + check_lib fam.h FAMOpen -lfam || die "Error, can't find libfam (install it or use --disable-fam) !" + add_cflags -DHAVE_FAM -pthread + add_extralibs -lpthread +fi + +################################################# # logging result ################################################# echolog "" @@ -677,7 +702,9 @@ echolog "configuration:" echolog " install prefix $PREFIX" echolog " configuration dir $sysconfdir" +echolog " data dir $datadir" echolog " locales dir $localedir" +echolog " mans dir $mandir" echolog " NLS support $nls" echolog " DLNA support $dlna" echolog " C compiler $cc" @@ -703,10 +730,12 @@ append_config "VERSION=$VERSION" append_config "PREFIX=$PREFIX" -append_config "prefix=\$(DESTDIR)\$(PREFIX)" -append_config "bindir=\$(DESTDIR)$bindir" -append_config "sysconfdir=\$(DESTDIR)$sysconfdir" -append_config "localedir=\$(DESTDIR)$localedir" +append_config "prefix=\$(PREFIX)" +append_config "bindir=$bindir" +append_config "sysconfdir=$sysconfdir" +append_config "datadir=$datadir" +append_config "localedir=$localedir" +append_config "mandir=$mandir" append_config "MAKE=$make" append_config "CC=$cc" only in patch2: unchanged: --- ushare-1.1a.orig/scripts/Makefile +++ ushare-1.1a/scripts/Makefile @@ -15,10 +15,10 @@ distclean: install: - $(INSTALL) -d $(sysconfdir) - $(INSTALL) -m 644 $(CONF_FILE) $(sysconfdir) - $(INSTALL) -d $(sysconfdir)/init.d - $(INSTALL) -m 755 $(INITD_FILE) $(sysconfdir)/init.d + $(INSTALL) -d $(DESTDIR)$(sysconfdir) + $(INSTALL) -m 644 $(CONF_FILE) $(DESTDIR)$(sysconfdir) + $(INSTALL) -d $(DESTDIR)$(sysconfdir)/init.d + $(INSTALL) -m 755 $(INITD_FILE) $(DESTDIR)$(sysconfdir)/init.d dist-all: cp $(EXTRADIST) $(SRCS) Makefile $(DIST) only in patch2: unchanged: --- ushare-1.1a.orig/scripts/ushare.conf +++ ushare-1.1a/scripts/ushare.conf @@ -31,15 +31,15 @@ USHARE_OVERRIDE_ICONV_ERR= # Enable Web interface (yes/no) -ENABLE_WEB= +USHARE_ENABLE_WEB= # Enable Telnet control interface (yes/no) -ENABLE_TELNET= +USHARE_ENABLE_TELNET= # Use XboX 360 compatibility mode (yes/no) -ENABLE_XBOX= +USHARE_ENABLE_XBOX= # Use DLNA profile (yes/no) # This is needed for PlayStation3 to work (among other devices) -ENABLE_DLNA= +USHARE_ENABLE_DLNA= only in patch2: unchanged: --- ushare-1.1a.orig/src/Makefile +++ ushare-1.1a/src/Makefile @@ -4,8 +4,9 @@ include ../config.mak PROG = ushare +MANS = ushare.1 -EXTRADIST = ushare.1 \ +EXTRADIST = \ cds.h \ cms.h \ msr.h \ @@ -25,26 +26,28 @@ ushare.h \ gettext.h \ minmax.h \ + ufam.h \ SRCS = \ - cds.c \ - cms.c \ - msr.c \ - http.c \ - presentation.c \ - metadata.c \ - mime.c \ - services.c \ - buffer.c \ - util_iconv.c \ - content.c \ - cfgparser.c \ - trace.c \ - redblack.c \ - osdep.c \ - ctrl_telnet.c \ - ushare.c + cds.c \ + cms.c \ + msr.c \ + http.c \ + presentation.c \ + metadata.c \ + mime.c \ + services.c \ + buffer.c \ + util_iconv.c \ + content.c \ + cfgparser.c \ + trace.c \ + redblack.c \ + osdep.c \ + ctrl_telnet.c \ + ufam.c \ + ushare.c OBJS = $(SRCS:.c=.o) @@ -64,18 +67,25 @@ distclean: -install: $(PROG) - $(INSTALL) -d $(bindir) - $(INSTALL) $(PROG) $(bindir) - $(STRIP) $(INSTALLSTRIP) $(bindir)/$(PROG) +install: $(PROG) install-man + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) $(PROG) $(DESTDIR)$(bindir) + $(STRIP) $(INSTALLSTRIP) $(DESTDIR)$(bindir)/$(PROG) + +install-man: $(MANS) + for m in $(MANS); do \ + section=`echo $$m | sed -e 's/^.*\\.//'`; \ + $(INSTALL) -d $(DESTDIR)$(mandir)/man$$section; \ + $(INSTALL) $$m $(DESTDIR)$(mandir)/man$$section; \ + done depend: $(CC) -I.. -MM $(CFLAGS) $(SRCS) 1>.depend -.PHONY: clean distclean install depend +.PHONY: clean distclean install depend install-man dist-all: - cp $(EXTRADIST) $(SRCS) Makefile $(DIST) + cp $(EXTRADIST) $(SRCS) Makefile $(MANS) $(DIST) .PHONY: dist-all only in patch2: unchanged: --- ushare-1.1a.orig/src/cds.c +++ ushare-1.1a/src/cds.c @@ -223,6 +223,11 @@ static bool cds_get_sort_capabilities (struct action_event_t *event) { +/* TODO: add the correct sort capabilities we made + * example from ยง 2.8.3.1. "Retrieving sort capabilities" of + * UpnP ContentDirectory 1.0 specifications + * "dc:title,dc:creator,dc:date,res@size" + */ upnp_add_response (event, SERVICE_CDS_ARG_SORT_CAPS, ""); return event->status; @@ -529,7 +534,10 @@ entry = upnp_get_entry (ut, id); if (!entry && (id < ut->starting_id)) - entry = upnp_get_entry (ut, ut->starting_id); + { + //entry = upnp_get_entry (ut, ut->starting_id); + entry = upnp_get_entry (ut, 0); + } if (!entry) { @@ -623,23 +631,24 @@ result = true; else if (protocol_contains && strstr (protocol, keyword)) result = true; - else if (entry->mime_type && - !strcmp (entry->mime_type->mime_class, keyword)) + else if (entry->mime_type && !strcmp(entry->mime_type->mime_class, keyword)) result = true; free (protocol); - + + and_clause = strstr (search_criteria, SEARCH_AND); if (and_clause) - return (result && - matches_search (and_clause + strlen (SEARCH_AND) -1, entry)); + { + return (result && matches_search (and_clause + strlen (SEARCH_AND) -1, entry)); + } - return true; + return result; /****** BUG Why keep track of result if we just return true! ********/ } static int -cds_search_directchildren_recursive (struct buffer_t *out, int count, +cds_search_directchildren_recursive (struct buffer_t *out, int count, int index, struct upnp_entry_t *entry, char *filter, - char *search_criteria) + char *search_criteria, char *sort_criteria) { struct upnp_entry_t **childs; int result_count = 0; @@ -647,9 +656,20 @@ if (entry->child_count == -1) /* item : file */ return -1; + /* go to the first child */ childs = entry->childs; + + + /* TODO: add the sort function, to sort the list with + * the sort_criteria parameter + * + * - make a new temporary list, duplicating current + * - sort this list + * - do the loop on the new list + */ + for (; *childs; childs++) { if (count == 0 || result_count < count) @@ -659,14 +679,17 @@ { int new_count; new_count = cds_search_directchildren_recursive - (out, (count == 0) ? 0 : (count - result_count), - (*childs), filter, search_criteria); + (out, (count == 0) ? 0 : ( count - result_count), index - result_count, + (*childs), filter, search_criteria, sort_criteria); result_count += new_count; } else /* item */ { if (matches_search (search_criteria, *childs)) { + result_count++; + if(result_count >= index) + { #ifdef HAVE_DLNA extern struct ushare_t *ut; #endif /* HAVE_DLNA */ @@ -695,7 +718,7 @@ (*childs)->title, protocol, (*childs)->size, (*childs)->url, filter); free (protocol); - result_count++; + } } } } @@ -708,13 +731,14 @@ cds_search_directchildren (struct action_event_t *event, struct buffer_t *out, int index, int count, struct upnp_entry_t *entry, - char *filter, char *search_criteria) + char *filter, char *search_criteria, + char *sort_criteria) { struct upnp_entry_t **childs; int s, result_count = 0; char tmp[32]; - index = 0; + //index = 0; if (entry->child_count == -1) /* item : file */ return -1; @@ -723,9 +747,9 @@ /* go to the child pointed out by index */ childs = entry->childs; - for (s = 0; s < index; s++) + /*for (s = 0; s < index; s++) if (*childs) - childs++; + childs++;*/ /* UPnP CDS compliance : If starting index = 0 and requested count = 0 then all children must be returned */ @@ -734,21 +758,24 @@ for (; *childs; childs++) { - if (count == 0 || result_count < count) + if (count == 0 || result_count < (count+index)) /* only fetch the requested count number or all entries if count = 0 */ { if ((*childs)->child_count >= 0) /* container */ { int new_count; new_count = cds_search_directchildren_recursive - (out, (count == 0) ? 0 : (count - result_count), - (*childs), filter, search_criteria); + (out, (count == 0) ? 0 : ( (count+index) - result_count), index - result_count, + (*childs), filter, search_criteria, sort_criteria); result_count += new_count; } else /* item */ { if (matches_search (search_criteria, *childs)) { + result_count++; + if(result_count >= index) + { #ifdef HAVE_DLNA extern struct ushare_t *ut; #endif /* HAVE_DLNA */ @@ -777,7 +804,7 @@ (*childs)->title, protocol, (*childs)->size, (*childs)->url, filter); free (protocol); - result_count++; + } } } } @@ -787,7 +814,7 @@ upnp_add_response (event, SERVICE_CDS_DIDL_RESULT, out->buf); - sprintf (tmp, "%d", result_count); + sprintf (tmp, "%d", result_count-index); upnp_add_response (event, SERVICE_CDS_DIDL_NUM_RETURNED, tmp); sprintf (tmp, "%d", result_count); upnp_add_response (event, SERVICE_CDS_DIDL_TOTAL_MATCH, tmp); @@ -795,13 +822,13 @@ return result_count; } -static bool -cds_search (struct action_event_t *event) +static bool cds_search (struct action_event_t *event) { extern struct ushare_t *ut; struct upnp_entry_t *entry = NULL; - int result_count = 0, index, count, id, sort_criteria; + int result_count = 0, index, count, id; char *search_criteria = NULL; + char *sort_criteria = NULL; char *filter = NULL; struct buffer_t *out = NULL; @@ -824,15 +851,22 @@ search_criteria = upnp_get_string (event->request, SERVICE_CDS_ARG_SEARCH_CRIT); filter = upnp_get_string (event->request, SERVICE_CDS_ARG_FILTER); - sort_criteria = upnp_get_ui4 (event->request, SERVICE_CDS_ARG_SORT_CRIT); + sort_criteria = upnp_get_string (event->request, SERVICE_CDS_ARG_SORT_CRIT); - if (!search_criteria || !filter) - return false; - - entry = upnp_get_entry (ut, id); + if (!search_criteria || !filter || !sort_criteria) + return false; - if (!entry && (id < ut->starting_id)) - entry = upnp_get_entry (ut, ut->starting_id); + /* Don't confuse the 360 container IDs with uShares content directory container IDs */ + if(ut->xbox360) + { + entry = upnp_get_entry (ut, 0); + } + else + { + entry = upnp_get_entry (ut, id); + if (!entry && (id < ut->starting_id)) + entry = upnp_get_entry (ut, ut->starting_id); + } if (!entry) return false; @@ -843,7 +877,7 @@ result_count = cds_search_directchildren (event, out, index, count, entry, - filter, search_criteria); + filter, search_criteria, sort_criteria); if (result_count < 0) { @@ -855,6 +889,7 @@ upnp_add_response (event, SERVICE_CDS_DIDL_UPDATE_ID, SERVICE_CDS_ROOT_OBJECT_ID); + free (sort_criteria); free (search_criteria); free (filter); only in patch2: unchanged: --- ushare-1.1a.orig/src/ufam.c +++ ushare-1.1a/src/ufam.c @@ -0,0 +1,259 @@ +/* + * ufam.c : GeeXboX uShare file alterative monitor + * Originally developped for the GeeXboX project. + * Copyright (C) 2005-2007 Alexis Saettler + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_FAM + +#include +#include +#include +#include +#include +#include + +#include "ushare.h" +#include "metadata.h" +#include "gettext.h" +#include "trace.h" +#include "mime.h" +#include "ufam.h" + + +/** + * ufam_entry_new : return a malloc'd ufam_entry_t struct + */ +struct ufam_entry_t * +ufam_entry_new (struct ufam_t *ufam, struct upnp_entry_t *entry) +{ + struct ufam_entry_t *ufam_entry = NULL; + + ufam_entry = (struct ufam_entry_t *) malloc (sizeof (struct ufam_entry_t)); + if (!ufam_entry) + return NULL; + + ufam_entry->ufam = ufam; + ufam_entry->entry = entry; + + return ufam_entry; +} + +/** + * ufam_entry_free: destroy ufam_entry + */ +void +ufam_entry_free (struct ufam_entry_t *ufam_entry) +{ + if (!ufam_entry) + return; + + free (ufam_entry); +} + + +/** + * ufam_thread: new thread to monitor changes in FAM Events + * @arg: is a struct ushare_t* var + */ +static void * +ufam_thread (void *arg) +{ + int rc; + FAMEvent fe; + struct upnp_entry_t *entry; + struct ushare_t *ut = (struct ushare_t*) arg; + + while (true) + { + pthread_mutex_lock (&ut->ufam->startstop_lock); + if (ut->ufam->stop) + { + pthread_cond_signal (&ut->ufam->stop_cond); + pthread_mutex_unlock (&ut->ufam->startstop_lock); + break; + } + pthread_mutex_unlock (&ut->ufam->startstop_lock); + + rc = FAMPending(&ut->ufam->fc); + if (rc == -1) + perror("FAMPending"); + + if (rc > 0) + { + if (FAMNextEvent(&ut->ufam->fc, &fe) < 0) + { + perror("FAMNextEvent"); + exit(1); + } + switch ((int)fe.code) + { + case FAMChanged: + case FAMDeleted: + case FAMCreated: + case FAMMoved: + entry = (struct upnp_entry_t *) fe.userdata; + if (entry) + log_verbose(_("ufam - dir %s has changed\n"), entry->fullpath); + /* TODO : rebuild metadat_list for this dir instead of rebuild from scratch */ + free_metadata_list (ut); + build_metadata_list (ut); + break; + } + } + } + + pthread_exit (NULL); + return NULL; +} + + +/** + * ufam_init: initialize a new FAM instance + */ +struct ufam_t * +ufam_init (void) +{ + struct ufam_t *ufam = NULL; + + ufam = (struct ufam_t *) malloc (sizeof (struct ufam_t)); + if (!ufam) + return NULL; + + pthread_mutex_init (&ufam->startstop_lock, NULL); + pthread_cond_init (&ufam->stop_cond, NULL); + pthread_mutex_init (&ufam->add_monitor_lock, NULL); + ufam->stop = false; + + pthread_mutex_lock (&ufam->startstop_lock); + + if ((FAMOpen2(&ufam->fc,"ushare")) < 0) + { + perror("fam"); + exit(1); + } + + pthread_mutex_unlock (&ufam->startstop_lock); + + return ufam; +} + + +/** + * ufam_start: start the FAM instance - launch the new thread + */ +void +ufam_start (struct ushare_t *ut) +{ + + pthread_mutex_lock (&ut->ufam->startstop_lock); + + if (pthread_create (&ut->ufam->thread, NULL, ufam_thread, (void*) ut)) + { + perror ("Failed to create thread"); + pthread_mutex_unlock (&ut->ufam->startstop_lock); + return; + } + + pthread_mutex_unlock (&ut->ufam->startstop_lock); +} + +/** + * ufam_stop: stop the FAM instance and wait thread to finish + */ +void +ufam_stop (struct ufam_t *ufam) +{ + if (!ufam) + return; + + pthread_mutex_lock (&ufam->startstop_lock); + ufam->stop = true; + pthread_cond_wait (&ufam->stop_cond, &ufam->startstop_lock); + + pthread_join (ufam->thread, NULL); + + pthread_mutex_unlock (&ufam->startstop_lock); +} + +/** + * ufam_free: free and close the FAM instance + */ +void +ufam_free (struct ufam_t *ufam) +{ + if (!ufam) + return; + + pthread_cond_destroy (&ufam->stop_cond); + pthread_mutex_destroy (&ufam->add_monitor_lock); + pthread_mutex_destroy (&ufam->startstop_lock); + + if (&ufam->fc) + FAMClose(&ufam->fc); + + free (ufam); +} + + +/** + * ufam_add_monitor: add a new monitor for this entry + * note: should only be a Directory to monitor + * TODO: check that entry is a directory + */ +struct ufam_entry_t * +ufam_add_monitor(struct ufam_t *ufam, struct upnp_entry_t *entry) +{ + struct ufam_entry_t *ufam_entry = NULL; + + if (!entry->fullpath) + return NULL; + + //log_verbose("ufam - new monitor for %s\n", entry->fullpath); + pthread_mutex_lock (&ufam->add_monitor_lock); + + ufam_entry = ufam_entry_new (ufam, entry); + + if (FAMMonitorDirectory(&ufam->fc, entry->fullpath, &ufam_entry->fr , (void*) entry ) < 0) + { + perror("FAMMonitor failed"); + exit(1); + } + + pthread_mutex_unlock (&ufam->add_monitor_lock); + + return ufam_entry; +} + +/** + * ufam_remove_monitor: remove this entry from the FAM instance + */ +void +ufam_remove_monitor (struct ufam_entry_t *ufam_entry) +{ + if (!ufam_entry) + return; + + pthread_mutex_lock (&ufam_entry->ufam->add_monitor_lock); + FAMCancelMonitor(&ufam_entry->ufam->fc, &ufam_entry->fr); + pthread_mutex_unlock (&ufam_entry->ufam->add_monitor_lock); + + ufam_entry_free (ufam_entry); +} + +#endif /* HAVE_FAM */ only in patch2: unchanged: --- ushare-1.1a.orig/src/ushare.h +++ ushare-1.1a/src/ushare.h @@ -119,6 +119,9 @@ char *cfg_file; pthread_mutex_t termination_mutex; pthread_cond_t termination_cond; +#ifdef HAVE_FAM + struct ufam_t *ufam; +#endif /* HAVE_FAM */ }; struct action_event_t { only in patch2: unchanged: --- ushare-1.1a.orig/src/ushare.c +++ ushare-1.1a/src/ushare.c @@ -72,6 +72,9 @@ #include "trace.h" #include "buffer.h" #include "ctrl_telnet.h" +#ifdef HAVE_FAM +#include "ufam.h" +#endif /* HAVE_FAM */ struct ushare_t *ut = NULL; @@ -115,6 +118,9 @@ ut->daemon = false; ut->override_iconv_err = false; ut->cfg_file = NULL; +#ifdef HAVE_FAM + ut->ufam = ufam_init (); +#endif /* HAVE_FAM */ pthread_mutex_init (&ut->termination_mutex, NULL); pthread_cond_init (&ut->termination_cond, NULL); @@ -157,6 +163,11 @@ if (ut->cfg_file) free (ut->cfg_file); +#ifdef HAVE_FAM + if (ut->ufam) + ufam_free (ut->ufam); +#endif /* HAVE_FAM */ + pthread_cond_destroy (&ut->termination_cond); pthread_mutex_destroy (&ut->termination_mutex); @@ -265,6 +276,9 @@ return -1; log_info (_("Stopping UPnP Service ...\n")); +#ifdef HAVE_FAM + ufam_stop (ut->ufam); +#endif /* HAVE_FAM */ UpnpUnRegisterRootDevice (ut->dev); UpnpFinish (); @@ -397,6 +411,10 @@ log_info (_("Listening for control point connections ...\n")); +#ifdef HAVE_FAM + ufam_start (ut); +#endif /* HAVE_FAM */ + if (description) free (description); @@ -424,15 +442,13 @@ if ((itf->ifa_flags & IFF_UP) && !strncmp (itf->ifa_name, interface, IFNAMSIZ)) { - log_error (_("Interface %s is down.\n"), interface); - log_error (_("Recheck uShare's configuration and try again !\n")); freeifaddrs (itflist); return true; } itf = itf->ifa_next; } - freeifaddrs (itf); + freeifaddrs (itflist); #else int sock, i, n; struct ifconf ifc; only in patch2: unchanged: --- ushare-1.1a.orig/src/mime.c +++ ushare-1.1a/src/mime.c @@ -53,6 +53,7 @@ { "mpeg2", UPNP_VIDEO, "http-get:*:video/mpeg2:"}, { "m4v", UPNP_VIDEO, "http-get:*:video/mp4:"}, { "m4p", UPNP_VIDEO, "http-get:*:video/mp4:"}, + { "mp4", UPNP_VIDEO, "http-get:*:video/mp4:"}, { "mp4ps", UPNP_VIDEO, "http-get:*:video/x-nerodigital-ps:"}, { "ts", UPNP_VIDEO, "http-get:*:video/mpeg2:"}, { "ogm", UPNP_VIDEO, "http-get:*:video/mpeg:"}, @@ -79,7 +80,6 @@ { "mp1", UPNP_AUDIO, "http-get:*:audio/mp1:"}, { "mp2", UPNP_AUDIO, "http-get:*:audio/mp2:"}, { "mp3", UPNP_AUDIO, "http-get:*:audio/mpeg:"}, - { "mp4", UPNP_AUDIO, "http-get:*:audio/mp4:"}, { "m4a", UPNP_AUDIO, "http-get:*:audio/mp4:"}, { "ogg", UPNP_AUDIO, "http-get:*:audio/x-ogg:"}, { "wav", UPNP_AUDIO, "http-get:*:audio/wav:"}, only in patch2: unchanged: --- ushare-1.1a.orig/src/metadata.h +++ ushare-1.1a/src/metadata.h @@ -44,6 +44,9 @@ char *url; off_t size; int fd; +#ifdef HAVE_FAM + struct ufam_entry_t *ufam_entry; +#endif /* HAVE_FAM */ }; typedef struct xml_convert_s { only in patch2: unchanged: --- ushare-1.1a.orig/src/ufam.h +++ ushare-1.1a/src/ufam.h @@ -0,0 +1,60 @@ +/* + * ufam.h : GeeXboX uShare file alterative monitor headers + * Originally developped for the GeeXboX project. + * Copyright (C) 2005-2007 Alexis Saettler + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _UFAM_H_ +#define _UFAM_H_ + +#ifdef HAVE_FAM + +#include +#include +#include + +#include "ushare.h" +#include "metadata.h" + +struct ufam_t { + FAMConnection fc; + + pthread_t thread; + pthread_mutex_t startstop_lock; + pthread_cond_t stop_cond; + pthread_mutex_t add_monitor_lock; + bool stop; +}; + +struct ufam_entry_t { + struct ufam_t *ufam; + struct upnp_entry_t *entry; + FAMRequest fr; +}; + +struct ufam_t *ufam_init (void); +void ufam_free (struct ufam_t *ufam); + +void ufam_start (struct ushare_t *ut); +void ufam_stop (struct ufam_t *ufam); + +struct ufam_entry_t *ufam_add_monitor (struct ufam_t *ufam, struct upnp_entry_t *entry); +void ufam_remove_monitor (struct ufam_entry_t *ufam_entry); + +#endif /* HAVE_FAM */ + +#endif /* _UFAM_H_ */ only in patch2: unchanged: --- ushare-1.1a.orig/src/metadata.c +++ ushare-1.1a/src/metadata.c @@ -37,6 +37,10 @@ #include "gettext.h" #include "trace.h" +#ifdef HAVE_FAM +#include "ufam.h" +#endif /* HAVE_FAM */ + #define TITLE_UNKNOWN "unknown" #define MAX_URL_SIZE 32 @@ -206,6 +210,9 @@ entry->parent = parent; entry->child_count = dir ? 0 : -1; entry->title = NULL; +#ifdef HAVE_FAM + entry->ufam_entry = NULL; +#endif /* HAVE_FAM */ entry->childs = (struct upnp_entry_t **) malloc (sizeof (struct upnp_entry_t *)); @@ -243,6 +250,9 @@ { entry->mime_type = &Container_MIME_Type; entry->url = NULL; +#ifdef HAVE_FAM + entry->ufam_entry = ufam_add_monitor (ut->ufam, entry); +#endif /* HAVE_FAM */ } /* Try Iconv'ing the name but if it fails the end device @@ -294,15 +304,13 @@ return entry; } -/* Seperate recursive free() function in order to avoid freeing off - * the parents child list within the freeing of the first child, as - * the only entry which is not part of a childs list is the root entry +/** + * Free all variables of entry, but childs* + * This function is not recursive. */ static void _upnp_entry_free (struct upnp_entry_t *entry) { - struct upnp_entry_t **childs; - if (!entry) return; @@ -316,10 +324,36 @@ if (entry->dlna_profile) entry->dlna_profile = NULL; #endif /* HAVE_DLNA */ +#ifdef HAVE_FAM + if (entry->ufam_entry) + { + ufam_remove_monitor (entry->ufam_entry); + entry->ufam_entry = NULL; + } +#endif /* HAVE_FAM */ + if (entry->childs) + free (entry->childs); - for (childs = entry->childs; *childs; childs++) - _upnp_entry_free (*childs); - free (entry->childs); + free (entry); +} + +/* Seperate recursive free() function in order to avoid freeing off + * the parents child list within the freeing of the first child, as + * the only entry which is not part of a childs list is the root entry + */ +static void +_upnp_entry_recursive_free (struct upnp_entry_t *entry) +{ + struct upnp_entry_t **childs; + + if (!entry) + return; + + if (entry->childs) + for (childs = entry->childs; *childs; childs++) + _upnp_entry_recursive_free (*childs); + + _upnp_entry_free (entry); } void @@ -344,14 +378,7 @@ entry_found = lk->entry_ptr; if (entry_found) { - if (entry_found->fullpath) - free (entry_found->fullpath); - if (entry_found->title) - free (entry_found->title); - if (entry_found->url) - free (entry_found->url); - - free (entry_found); + _upnp_entry_free (entry_found); i++; } @@ -363,12 +390,13 @@ rbdestroy (ut->rb); ut->rb = NULL; + /* Free the root_entry : */ + _upnp_entry_free (entry); + log_verbose ("Freed [%d] entries\n", i); } else - _upnp_entry_free (entry); - - free (entry); + _upnp_entry_recursive_free (entry); } static void