Skip to content
This repository has been archived by the owner on Dec 14, 2020. It is now read-only.

Commit

Permalink
minidlna: Updated to 1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
RMerl committed May 25, 2017
1 parent 8b47362 commit c0642b4
Show file tree
Hide file tree
Showing 30 changed files with 1,118 additions and 940 deletions.
26 changes: 16 additions & 10 deletions release/src/router/minidlna/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,24 @@ minidlnad_SOURCES = minidlna.c upnphttp.c upnpdescgen.c upnpsoap.c \
upnpreplyparse.c minixml.c clients.c \
getifaddr.c process.c upnpglobalvars.c \
options.c minissdp.c uuid.c upnpevents.c \
sql.c utils.c metadata.c scanner.c inotify.c \
sql.c utils.c metadata.c scanner.c monitor.c \
tivo_utils.c tivo_beacon.c tivo_commands.c \
playlist.c image_utils.c albumart.c log.c \
containers.c tagutils/tagutils.c
containers.c avahi.c tagutils/tagutils.c

#if NEED_VORBIS
vorbisflag = -lvorbis
#endif
if HAVE_VORBISFILE
vorbislibs = -lvorbis -logg
else
if NEED_OGG
flacogglibs = -logg
endif
endif

#if NEED_OGG
flacoggflag = -logg
#endif
if TIVO_SUPPORT
if HAVE_AVAHI
avahilibs = -lavahi-client -lavahi-common
endif
endif

minidlnad_LDADD = \
@LIBJPEG_LIBS@ \
Expand All @@ -47,7 +53,7 @@ minidlnad_LDADD = \
@LIBEXIF_LIBS@ \
@LIBINTL@ \
@LIBICONV@ \
-lFLAC $(flacoggflag) $(vorbisflag)
-lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs)

minidlnad_LDFLAGS = @STATIC_LDFLAGS@

Expand All @@ -59,7 +65,7 @@ testupnpdescgen_LDADD = \
@LIBAVFORMAT_LIBS@ \
@LIBAVUTIL_LIBS@ \
@LIBEXIF_LIBS@ \
-lFLAC $(flacoggflag) $(vorbisflag)
-lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs)

SUFFIXES = .tmpl .

Expand Down
9 changes: 9 additions & 0 deletions release/src/router/minidlna/NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
1.2.0 - Released 17-May-2017
--------------------------------
- Add libavformat > 57 compatibility.
- Add TiVo Bonjour discovery support using Avahi for Bolt.
- Improve Samsung BD-J5500 support.
- Add quirk to fix video playback on Hyundai TVs.
- Add non-destructive update rescan support.
- Enhance bookmark support to work with Kodi.

1.1.6 - Released 16-June-2016
--------------------------------
- Add AllShare and Windows client detection.
Expand Down
246 changes: 246 additions & 0 deletions release/src/router/minidlna/avahi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
/* MiniDLNA media server
* Copyright (C) 2017 NETGEAR
*
* This file is part of MiniDLNA.
*
* MiniDLNA is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* MiniDLNA 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
*/

/* This file is loosely based on examples from zeroconf_avahi_demos:
* http://wiki.ros.org/zeroconf_avahi_demos
* with some ideas from Netatalk's Avahi implementation.
*/

#include <config.h>

#if defined(TIVO_SUPPORT) && defined(HAVE_AVAHI)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>

#include <avahi-common/error.h>
#include <avahi-common/thread-watch.h>
#include <avahi-client/publish.h>

#include "upnpglobalvars.h"
#include "log.h"

static struct context {
AvahiThreadedPoll *threaded_poll;
AvahiClient *client;
AvahiEntryGroup *group;
} ctx;

/*****************************************************************
* Private functions
*****************************************************************/

static void publish_reply(AvahiEntryGroup *g,
AvahiEntryGroupState state,
void *userdata);

static int
_add_svc(const char *cat, const char *srv, const char *id, const char *platform)
{
char name[128+1];
char path[64];
int ret;

snprintf(name, sizeof(name), "%s on %s", cat, friendly_name);
snprintf(path, sizeof(path),
"path=/TiVoConnect?Command=QueryContainer&Container=%s", id);

DPRINTF(E_INFO, L_SSDP, "Registering '%s'\n", name);
ret = avahi_entry_group_add_service(ctx.group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
0, name, srv, NULL, NULL, runtime_vars.port,
"protocol=http", path, platform, NULL);
if (ret < 0)
DPRINTF(E_ERROR, L_SSDP, "Failed to add %s: %s\n",
srv, avahi_strerror(avahi_client_errno(ctx.client)));
return ret;
}

/* Try to register the TiVo DNS SRV service type. */
static void
register_stuff(void)
{
assert(ctx.client);

if (!ctx.group)
{
ctx.group = avahi_entry_group_new(ctx.client, publish_reply, NULL);
if (!ctx.group)
{
DPRINTF(E_ERROR, L_SSDP, "Failed to create entry group: %s\n",
avahi_strerror(avahi_client_errno(ctx.client)));
return;
}
}

if (avahi_entry_group_is_empty(ctx.group))
{
if (_add_svc("Music", "_tivo-music._tcp", "1", NULL) < 0)
return;
if (_add_svc("Photos", "_tivo-photos._tcp", "3", NULL) < 0)
return;
if (_add_svc("Videos", "_tivo-videos._tcp", "2", "platform=pc/readydlna") < 0)
return;
if (avahi_entry_group_commit(ctx.group) < 0)
{
DPRINTF(E_ERROR, L_SSDP, "Failed to commit entry group: %s\n",
avahi_strerror(avahi_client_errno(ctx.client)));
return;
}
}
}

/* Called when publishing of service data completes */
static void publish_reply(AvahiEntryGroup *g,
AvahiEntryGroupState state,
AVAHI_GCC_UNUSED void *userdata)
{
assert(ctx.group == NULL || g == ctx.group);

switch (state) {
case AVAHI_ENTRY_GROUP_ESTABLISHED:
/* The entry group has been established successfully */
DPRINTF(E_MAXDEBUG, L_SSDP, "publish_reply: AVAHI_ENTRY_GROUP_ESTABLISHED\n");
break;
case AVAHI_ENTRY_GROUP_COLLISION:
/* With multiple names there's no way to know which one collided */
DPRINTF(E_ERROR, L_SSDP, "publish_reply: AVAHI_ENTRY_GROUP_COLLISION: %s\n",
avahi_strerror(avahi_client_errno(ctx.client)));
avahi_threaded_poll_quit(ctx.threaded_poll);
break;
case AVAHI_ENTRY_GROUP_FAILURE:
DPRINTF(E_ERROR, L_SSDP, "Failed to register service: %s\n",
avahi_strerror(avahi_client_errno(ctx.client)));
avahi_threaded_poll_quit(ctx.threaded_poll);
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
case AVAHI_ENTRY_GROUP_REGISTERING:
default:
break;
}
}

static void client_callback(AvahiClient *client,
AvahiClientState state,
void *userdata)
{
ctx.client = client;

switch (state) {
case AVAHI_CLIENT_S_RUNNING:
/* The server has started up successfully and registered its host
* name on the network, so it's time to create our services */
register_stuff();
break;
case AVAHI_CLIENT_S_COLLISION:
case AVAHI_CLIENT_S_REGISTERING:
if (ctx.group)
avahi_entry_group_reset(ctx.group);
break;
case AVAHI_CLIENT_FAILURE:
if (avahi_client_errno(client) == AVAHI_ERR_DISCONNECTED)
{
int error;

avahi_client_free(ctx.client);
ctx.client = NULL;
ctx.group = NULL;

/* Reconnect to the server */
ctx.client = avahi_client_new(
avahi_threaded_poll_get(ctx.threaded_poll),
AVAHI_CLIENT_NO_FAIL, client_callback,
&ctx, &error);
if (!ctx.client)
{
DPRINTF(E_ERROR, L_SSDP,
"Failed to contact server: %s\n",
avahi_strerror(error));
avahi_threaded_poll_quit(ctx.threaded_poll);
}
}
else
{
DPRINTF(E_ERROR, L_SSDP, "Client failure: %s\n",
avahi_strerror(avahi_client_errno(client)));
avahi_threaded_poll_quit(ctx.threaded_poll);
}
break;
case AVAHI_CLIENT_CONNECTING:
default:
break;
}
}

/************************************************************************
* Public funcions
************************************************************************/

/*
* Tries to shutdown this loop impl.
* Call this function from inside this thread.
*/
void tivo_bonjour_unregister(void)
{
DPRINTF(E_DEBUG, L_SSDP, "tivo_bonjour_unregister\n");

if (ctx.threaded_poll)
avahi_threaded_poll_stop(ctx.threaded_poll);
if (ctx.client)
avahi_client_free(ctx.client);
if (ctx.threaded_poll)
avahi_threaded_poll_free(ctx.threaded_poll);
}

/*
* Tries to setup the Zeroconf thread and any
* neccessary config setting.
*/
void tivo_bonjour_register(void)
{
int error;

/* first of all we need to initialize our threading env */
ctx.threaded_poll = avahi_threaded_poll_new();
if (!ctx.threaded_poll)
return;

/* now we need to acquire a client */
ctx.client = avahi_client_new(avahi_threaded_poll_get(ctx.threaded_poll),
AVAHI_CLIENT_NO_FAIL, client_callback, NULL, &error);
if (!ctx.client)
{
DPRINTF(E_ERROR, L_SSDP, "Failed to create client object: %s\n",
avahi_strerror(error));
tivo_bonjour_unregister();
return;
}

if (avahi_threaded_poll_start(ctx.threaded_poll) < 0)
{
DPRINTF(E_ERROR, L_SSDP, "Failed to create thread: %s\n",
avahi_strerror(avahi_client_errno(ctx.client)));
tivo_bonjour_unregister();
}
else
DPRINTF(E_INFO, L_SSDP, "Successfully started avahi loop\n");
}
#endif /* HAVE_AVAHI */
9 changes: 9 additions & 0 deletions release/src/router/minidlna/avahi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "config.h"

#if defined(TIVO_SUPPORT) && defined(HAVE_AVAHI)
void tivo_bonjour_register(void);
void tivo_bonjour_unregister(void);
#else
static inline void tivo_bonjour_register(void) {};
static inline void tivo_bonjour_unregister(void) {};
#endif
24 changes: 22 additions & 2 deletions release/src/router/minidlna/clients.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* MiniDLNA media server
* Copyright (C) 2013 NETGEAR
* Copyright (C) 2013-2017 NETGEAR
*
* This file is part of MiniDLNA.
*
Expand Down Expand Up @@ -63,6 +63,13 @@ struct client_type_s client_types[] =
EUserAgent
},

{ ESamsungBDJ5500,
FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE | FLAG_CAPTION_RES | FLAG_SKIP_DLNA_PN,
"Samsung BD J5500",
"[BD]J5500",
EUserAgent
},

/* Samsung Series [CDE] BDPs and TVs must be separated, or some of our
* advertised extra features trigger a folder browsing bug on BDPs. */
/* User-Agent: DLNADOC/1.50 SEC_HHP_BD-D5100/1.0 */
Expand Down Expand Up @@ -198,6 +205,13 @@ struct client_type_s client_types[] =
EUserAgent
},

{ EHyundaiTV,
FLAG_DLNA,
"Hyundai TV",
"HYUNDAITV",
EFriendlyName
},

{ ERokuSoundBridge,
FLAG_MS_PFS | FLAG_AUDIO_ONLY | FLAG_MIME_WAV_WAV | FLAG_FORCE_SORT,
"Roku SoundBridge",
Expand Down Expand Up @@ -240,6 +254,13 @@ struct client_type_s client_types[] =
EUserAgent
},

{ EKodi,
FLAG_DLNA | FLAG_MIME_AVI_AVI | FLAG_CAPTION_RES,
"Kodi",
"Kodi",
EUserAgent
},

{ 0,
FLAG_DLNA | FLAG_MIME_AVI_AVI,
"Windows",
Expand Down Expand Up @@ -324,4 +345,3 @@ AddClientCache(struct in_addr addr, int type)

return NULL;
}

0 comments on commit c0642b4

Please sign in to comment.