Commit 31fee798 authored by W. Michael Petullo's avatar W. Michael Petullo

Deal with name collisions when sharing given type of service

Signed-off-by: W. Michael Petullo's avatarW. Michael Petullo <mike@flyn.org>
parent 4c1245a0
......@@ -3,7 +3,10 @@ versions. The primary reason for these changes is to better support
GObject introspection and thus languages such as Python. The following
are the key differences between the new and old APIs:
(1) All symbols now exist in the DMAP/Dmap/dmap namespace.
(1) A program which shares a DMAP service must explicitly call
dmap_share_serve() and dmap_share_publish().
(2) All symbols now exist in the DMAP/Dmap/dmap namespace.
(a) For example, DMAPDb is now DmapDb.
......@@ -17,10 +20,10 @@ are the key differences between the new and old APIs:
(e) DACPPlayer is now DmapControlPlayer.
(2) The interface names exported by libdmapsharing now end in "Interface"
(3) The interface names exported by libdmapsharing now end in "Interface"
instead of "Iface".
(3) The new API renames the following symbols as indicated:
(4) The new API renames the following symbols as indicated:
DMAP_TYPE_DMAP_MDNS_BROWSER_TRANSPORT_PROTOCOL became
DMAP_TYPE_DMAP_MDNS_SERVICE_TRANSPORT_PROTOCOL.
......@@ -47,17 +50,17 @@ instead of "Iface".
DACPPlayState became DmapControlPlayState.
(4) The new API replaces the use of GHFunc with DMAPIdRecordFunc and
(5) The new API replaces the use of GHFunc with DMAPIdRecordFunc and
DMAPContainerIdFunc.
(5) Setting an object property using g_object_set causes the object to
(6) Setting an object property using g_object_set causes the object to
duplicate the passed value. Thus the caller maintains control of the
original value.
(6) Getting an object property using g_object_set returns a duplicate
(7) Getting an object property using g_object_set returns a duplicate
of the value. Thus the caller should free or unref the obtained value.
(7) The "hash" property in the DAAPRecord interface and the "hash"
(8) The "hash" property in the DAAPRecord interface and the "hash"
and "thumbnail" properties in the DPAPRecord interface are now boxed
types. The true type of each of these properties is a GArray. Thus
implementations of these interfaces should now:
......@@ -68,11 +71,11 @@ implementations of these interfaces should now:
(c) use GArray instead of GByteArray.
(8) The "base-uri" property in the DMAPConnection class is now a boxed
(9) The "base-uri" property in the DMAPConnection class is now a boxed
type. The real type is SoupURI.
(9) The "db" and "container-db" properties in DMAPShare are now handled
(10) The "db" and "container-db" properties in DMAPShare are now handled
as object types instead of pointer types.
(10) The properties contained in a DMAPMdnsService must now be accessed
(11) The properties contained in a DMAPMdnsService must now be accessed
using g_object_get.
......@@ -97,37 +97,21 @@ dmap_av_share_init (DmapAvShare * share)
DmapAvShare *
dmap_av_share_new (const char *name,
const char *password,
DmapDb * db,
DmapContainerDb * container_db, gchar * transcode_mimetype)
const char *password,
DmapDb * db,
DmapContainerDb * container_db,
gchar * transcode_mimetype)
{
DmapAvShare *share;
g_object_ref (db);
g_object_ref (container_db);
share = DMAP_AV_SHARE (g_object_new (DMAP_TYPE_AV_SHARE,
"name", name,
"password", password,
"db", db,
"container-db", container_db,
"transcode-mimetype",
transcode_mimetype, NULL));
if (!dmap_share_server_start (DMAP_SHARE (share))) {
g_object_unref(share);
share = NULL;
goto done;
}
if (!dmap_share_publish_start (DMAP_SHARE (share))) {
g_object_unref(share);
share = NULL;
goto done;
}
done:
return share;
return DMAP_AV_SHARE (g_object_new (DMAP_TYPE_AV_SHARE,
"name", name,
"password", password,
"db", db,
"container-db", container_db,
"transcode-mimetype",
transcode_mimetype, NULL));
}
void
......@@ -1090,11 +1074,11 @@ START_TEST(dmap_av_share_new_test)
dmap_db_add(db, record);
share = DMAP_SHARE(dmap_av_share_new("name",
"password",
db,
container_db,
"audio/mp3"));
share = DMAP_SHARE(dmap_av_share_new("name",
"password",
db,
container_db,
"audio/mp3"));
g_object_get(share, "name", &str, NULL);
ck_assert_str_eq("name", str);
......@@ -1115,6 +1099,99 @@ START_TEST(dmap_av_share_new_test)
}
END_TEST
START_TEST(dmap_av_share_serve_publish_test)
{
DmapDb *db;
gboolean ok;
DmapContainerRecord *container_record;
DmapContainerDb *container_db;
DmapRecord *record;
DmapShare *share;
db = DMAP_DB(test_dmap_db_new());
container_record = DMAP_CONTAINER_RECORD (test_dmap_container_record_new ());
container_db = DMAP_CONTAINER_DB(test_dmap_container_db_new(container_record));
record = DMAP_RECORD(test_dmap_av_record_new());
g_object_set(record, "songgenre", "genre1", NULL);
g_object_set(record, "songartist", "artist1", NULL);
g_object_set(record, "songalbum", "album1", NULL);
dmap_db_add(db, record);
share = DMAP_SHARE(dmap_av_share_new("name",
"password",
db,
container_db,
"audio/mp3"));
ok = dmap_share_serve(share);
ck_assert(ok);
ok = dmap_share_publish(share);
ck_assert(ok);
g_object_unref(db);
g_object_unref(container_record);
g_object_unref(container_db);
g_object_unref(share);
}
END_TEST
START_TEST(dmap_av_share_serve_publish_collision_test)
{
DmapDb *db;
gboolean ok;
DmapContainerRecord *container_record;
DmapContainerDb *container_db;
DmapRecord *record;
DmapShare *share1, *share2;
db = DMAP_DB(test_dmap_db_new());
container_record = DMAP_CONTAINER_RECORD (test_dmap_container_record_new ());
container_db = DMAP_CONTAINER_DB(test_dmap_container_db_new(container_record));
record = DMAP_RECORD(test_dmap_av_record_new());
g_object_set(record, "songgenre", "genre1", NULL);
g_object_set(record, "songartist", "artist1", NULL);
g_object_set(record, "songalbum", "album1", NULL);
dmap_db_add(db, record);
share1 = DMAP_SHARE(dmap_av_share_new("name",
"password",
db,
container_db,
"audio/mp3"));
ok = dmap_share_serve(share1);
ck_assert(ok);
ok = dmap_share_publish(share1);
ck_assert(ok);
share2 = DMAP_SHARE(dmap_av_share_new("name",
"password",
db,
container_db,
"audio/mp3"));
ok = dmap_share_serve(share2);
ck_assert(ok);
ok = dmap_share_publish(share2);
ck_assert(ok);
g_object_unref(db);
g_object_unref(container_record);
g_object_unref(container_db);
g_object_unref(share1);
g_object_unref(share2);
}
END_TEST
static void
_tabulator_test(char *property,
void (*tabulator) (gpointer id, DmapRecord * record, GHashTable * ht))
......
......@@ -436,26 +436,22 @@ _mdns_remote_removed (DmapMdnsBrowser * browser,
}
DmapControlShare *
dmap_control_share_new (const gchar * library_name,
DmapControlPlayer * player,
DmapDb * db, DmapContainerDb * container_db)
dmap_control_share_new (const gchar *library_name,
DmapControlPlayer *player,
DmapDb *db,
DmapContainerDb *container_db)
{
DmapControlShare *share;
share = DMAP_CONTROL_SHARE (g_object_new (DMAP_TYPE_CONTROL_SHARE,
"name", _get_dbid (),
"library-name", library_name,
"password", NULL,
"db", db,
"container-db", container_db,
"player", G_OBJECT (player),
"transcode-mimetype", NULL, NULL));
g_debug ("Starting DACP server");
dmap_share_server_start (DMAP_SHARE (share));
dmap_share_publish_start (DMAP_SHARE (share));
return share;
g_object_ref (db);
g_object_ref (container_db);
return DMAP_CONTROL_SHARE (g_object_new (DMAP_TYPE_CONTROL_SHARE,
"name", _get_dbid (),
"library-name", library_name,
"password", NULL,
"db", db,
"container-db", container_db,
"player", G_OBJECT (player),
"transcode-mimetype", NULL, NULL));
}
void
......
......@@ -163,23 +163,20 @@ dmap_image_share_dispose (GObject * object)
*/
DmapImageShare *
dmap_image_share_new (const char *name,
const char *password,
gpointer db,
gpointer container_db, gchar * transcode_mimetype)
const char *password,
gpointer db,
gpointer container_db,
gchar * transcode_mimetype)
{
DmapImageShare *share;
share = DMAP_IMAGE_SHARE (g_object_new (DMAP_TYPE_IMAGE_SHARE,
"name", name,
"password", password,
"db", db,
"container-db", container_db,
NULL));
dmap_share_server_start (DMAP_SHARE (share));
dmap_share_publish_start (DMAP_SHARE (share));
return share;
g_object_ref (db);
g_object_ref (container_db);
return DMAP_IMAGE_SHARE (g_object_new (DMAP_TYPE_IMAGE_SHARE,
"name", name,
"password", password,
"db", db,
"container-db", container_db,
NULL));
}
void
......
......@@ -140,7 +140,8 @@ create_service (struct DmapMdnsPublisherService *service,
ret = avahi_entry_group_add_service_strlst (publisher->
priv->entry_group,
AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC, 0,
AVAHI_PROTO_UNSPEC,
0,
service->name,
service->type_of_service,
NULL, NULL, service->port,
......@@ -164,7 +165,10 @@ create_service (struct DmapMdnsPublisherService *service,
static gboolean
create_services (DmapMdnsPublisher * publisher, GError ** error)
{
GSList *ptr;
static int suffix = 0;
gchar *name;
GSList *ptr1, *ptr2;
struct DmapMdnsPublisherService *service1, *service2;
int ret;
if (publisher->priv->entry_group == NULL) {
......@@ -190,8 +194,25 @@ create_services (DmapMdnsPublisher * publisher, GError ** error)
avahi_entry_group_reset (publisher->priv->entry_group);
}
for (ptr = publisher->priv->service; ptr; ptr = g_slist_next (ptr)) {
if (!create_service (ptr->data, publisher, error)) {
for (ptr1 = publisher->priv->service; ptr1; ptr1 = g_slist_next (ptr1)) {
service1 = ptr1->data;
name = service1->name;
for (ptr2 = publisher->priv->service; ptr2; ptr2 = g_slist_next (ptr2)) {
if (ptr1 == ptr2) {
continue;
}
service2 = ptr2->data;
if (!strcmp(service1->name, service2->name)
&& !strcmp(service1->type_of_service, service2->type_of_service)) {
name = g_strdup_printf("%s-%d", service1->name, suffix++);
}
}
if (strcmp(name, service1->name)) {
g_free(service1->name);
service1->name = name;
g_signal_emit (publisher, signals[NAME_COLLISION], 0, name);
}
if (!create_service (service1, publisher, error)) {
return FALSE;
}
}
......
......@@ -220,7 +220,7 @@ _ctrl_int_adapter (SoupServer * server,
}
gboolean
dmap_share_server_start (DmapShare *share)
dmap_share_serve (DmapShare *share)
{
guint desired_port = DMAP_SHARE_GET_CLASS (share)->get_desired_port (share);
gboolean password_required, ok = FALSE;
......@@ -342,7 +342,7 @@ _server_stop (DmapShare * share)
}
gboolean
dmap_share_publish_start (DmapShare * share)
dmap_share_publish (DmapShare * share)
{
GError *error;
gboolean ok;
......@@ -411,10 +411,10 @@ _restart (DmapShare * share)
gboolean res;
_server_stop (share);
res = dmap_share_server_start (share);
res = dmap_share_serve (share);
if (res) {
/* To update information just publish again */
dmap_share_publish_start (share);
dmap_share_publish (share);
} else {
_publish_stop (share);
}
......@@ -456,12 +456,8 @@ _set_name (DmapShare * share, const char *name)
static void
_set_password (DmapShare * share, const char *password)
{
if (NULL != share) {
goto done;
}
if (share->priv->password && password &&
strcmp (password, share->priv->password) == 0) {
0 == strcmp (password, share->priv->password)) {
goto done;
}
......@@ -978,20 +974,13 @@ void
dmap_share_name_collision (DmapShare * share,
DmapMdnsPublisher * publisher, const char *name)
{
char *new_name = g_strdup("FIXME");
if (share->priv->name == NULL || name == NULL) {
goto done;
}
g_assert(NULL != name);
g_assert(NULL != share->priv->name);
if (strcmp (share->priv->name, name) == 0) {
g_warning ("Duplicate share name on mDNS");
g_warning ("Duplicate share name on mDNS; renaming share to %s", name);
_set_name (DMAP_SHARE (share), new_name);
g_free (new_name);
}
_set_name (DMAP_SHARE (share), name);
done:
return;
}
......
......@@ -191,6 +191,27 @@ struct DmapMlclBits
GType dmap_share_get_type (void);
/**
* dmap_share_serve:
* @share: a #DmapShare instance.
*
* Begin serving the service defined by share. A program will normally also
* call dmap_share_publish.
*
* Returns: TRUE if serving succeeds, else FALSE.
*/
gboolean dmap_share_serve(DmapShare *share);
/**
* dmap_share_publish:
* @share: a #DmapShare instance.
*
* Publish the availability of the given share using mDNS-SD.
*
* Returns: TRUE if publishing succeeds, else FALSE.
*/
gboolean dmap_share_publish(DmapShare *share);
/**
* dmap_share_free_filter:
* @filter: (element-type GSList): The filter list to free.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment