udapted vi.po
[rhythmbox.git] / daapsharing / rb-daap-mdns-publisher-howl.c
blob0a9f52f460d1ba474e021df08431a04b20227955
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * Copyright (C) 2005 Charles Schmidt <cschmidt2@emich.edu>
4 * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "config.h"
24 #include <stdlib.h>
25 #include <stdio.h>
27 #include <glib.h>
28 #include <glib/gi18n.h>
29 #include <glib-object.h>
31 /* stupid howl includes howl_config.h */
32 #undef PACKAGE
33 #undef VERSION
34 #include <howl.h>
36 #include "rb-daap-mdns-publisher.h"
37 #include "rb-debug.h"
39 static void rb_daap_mdns_publisher_class_init (RBDaapMdnsPublisherClass *klass);
40 static void rb_daap_mdns_publisher_init (RBDaapMdnsPublisher *publisher);
41 static void rb_daap_mdns_publisher_finalize (GObject *object);
43 #define RB_DAAP_MDNS_PUBLISHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_DAAP_MDNS_PUBLISHER, RBDaapMdnsPublisherPrivate))
45 struct RBDaapMdnsPublisherPrivate
47 sw_discovery *discovery;
48 sw_discovery_oid *oid;
50 guint watch_id;
52 char *name;
53 guint port;
54 gboolean password_required;
57 enum {
58 PUBLISHED,
59 NAME_COLLISION,
60 LAST_SIGNAL
63 enum {
64 PROP_0
67 static guint signals [LAST_SIGNAL] = { 0, };
69 G_DEFINE_TYPE (RBDaapMdnsPublisher, rb_daap_mdns_publisher, G_TYPE_OBJECT)
71 static gpointer publisher_object = NULL;
73 GQuark
74 rb_daap_mdns_publisher_error_quark (void)
76 static GQuark quark = 0;
77 if (!quark)
78 quark = g_quark_from_static_string ("rb_daap_mdns_publisher_error");
80 return quark;
83 static gboolean
84 howl_in_cb (GIOChannel *io_channel,
85 GIOCondition condition,
86 RBDaapMdnsPublisher *publisher)
88 sw_salt salt;
90 if (sw_discovery_salt (*publisher->priv->discovery, &salt) == SW_OKAY) {
91 sw_salt_lock (salt);
92 sw_discovery_read_socket (*publisher->priv->discovery);
93 sw_salt_unlock (salt);
96 return TRUE;
99 static void
100 howl_client_init (RBDaapMdnsPublisher *publisher)
102 sw_result result;
103 int fd;
104 GIOChannel *channel;
106 publisher->priv->discovery = g_new0 (sw_discovery, 1);
107 result = sw_discovery_init (publisher->priv->discovery);
109 if (result != SW_OKAY) {
110 g_free (publisher->priv->discovery);
111 publisher->priv->discovery = NULL;
112 return;
115 fd = sw_discovery_socket (*publisher->priv->discovery);
117 channel = g_io_channel_unix_new (fd);
118 publisher->priv->watch_id = g_io_add_watch (channel, G_IO_IN, (GIOFunc)howl_in_cb, publisher);
119 g_io_channel_unref (channel);
122 static sw_result
123 publish_cb (sw_discovery discovery,
124 sw_discovery_oid oid,
125 sw_discovery_publish_status status,
126 RBDaapMdnsPublisher *publisher)
128 if (status == SW_DISCOVERY_PUBLISH_STARTED) {
129 g_signal_emit (publisher, signals [PUBLISHED], 0, publisher->priv->name);
130 } else if (status == SW_DISCOVERY_PUBLISH_NAME_COLLISION) {
131 /* This is all well and good, but howl won't report a name collision.
132 * http://lists.porchdogsoft.com/pipermail/howl-users/Week-of-Mon-20041206/000487.html
133 * So. Fuck.
135 g_warning ("MDNS name collision");
137 g_signal_emit (publisher, signals [NAME_COLLISION], 0, publisher->priv->name);
140 return SW_OKAY;
143 static const char *
144 howl_strerror (sw_result result)
146 const char *str;
148 switch (result) {
149 case SW_OKAY:
150 str = "No error";
151 case SW_DISCOVERY_E_NO_MEM:
152 str = "Out of memory";
153 case SW_DISCOVERY_E_BAD_PARAM:
154 str = "Invalid paramater";
155 case SW_DISCOVERY_E_UNKNOWN:
156 default:
157 str = "Unknown error";
160 return str;
163 static gboolean
164 create_service (RBDaapMdnsPublisher *publisher,
165 GError **error)
167 sw_text_record text_record;
168 sw_result result;
170 if (sw_text_record_init (&text_record) != SW_OKAY) {
171 rb_debug ("Error initializing Howl text record");
172 g_set_error (error,
173 RB_DAAP_MDNS_PUBLISHER_ERROR,
174 RB_DAAP_MDNS_PUBLISHER_ERROR_FAILED,
175 "%s",
176 _("Error initializing Howl for publishing"));
177 return FALSE;
180 if (publisher->priv->oid != NULL) {
181 rb_daap_mdns_publisher_withdraw (publisher, NULL);
184 publisher->priv->oid = g_new0 (sw_discovery_oid, 1);
186 sw_text_record_add_key_and_string_value (text_record,
187 "Password",
188 publisher->priv->password_required ? "true" : "false");
190 result = sw_discovery_publish (*publisher->priv->discovery,
192 publisher->priv->name,
193 "_daap._tcp",
194 "local",
195 NULL,
196 publisher->priv->port,
197 sw_text_record_bytes (text_record),
198 sw_text_record_len (text_record),
199 (sw_discovery_publish_reply) publish_cb,
200 (sw_opaque) publisher,
201 (sw_discovery_oid *) publisher->priv->oid);
203 sw_text_record_fina (text_record);
205 if (result != SW_OKAY) {
206 rb_debug ("Error starting mDNS publish with Howl: %s", howl_strerror (result));
207 g_set_error (error,
208 RB_DAAP_MDNS_PUBLISHER_ERROR,
209 RB_DAAP_MDNS_PUBLISHER_ERROR_FAILED,
210 "%s: %s",
211 _("Error initializing Howl for publishing"),
212 howl_strerror (result));
213 return FALSE;
216 return TRUE;
219 static gboolean
220 refresh_service (RBDaapMdnsPublisher *publisher,
221 GError **error)
223 return create_service (publisher, error);
226 gboolean
227 rb_daap_mdns_publisher_publish (RBDaapMdnsPublisher *publisher,
228 const char *name,
229 guint port,
230 gboolean password_required,
231 GError **error)
233 if (publisher->priv->discovery == NULL) {
234 g_set_error (error,
235 RB_DAAP_MDNS_PUBLISHER_ERROR,
236 RB_DAAP_MDNS_PUBLISHER_ERROR_NOT_RUNNING,
237 "%s",
238 _("The howl MDNS service is not running"));
239 return FALSE;
242 rb_daap_mdns_publisher_set_name (publisher, name, NULL);
243 rb_daap_mdns_publisher_set_port (publisher, port, NULL);
244 rb_daap_mdns_publisher_set_password_required (publisher, password_required, NULL);
246 /* special case: the _set_ functions have updated the existing entry group */
247 if (publisher->priv->oid != NULL) {
248 return TRUE;
251 return create_service (publisher, error);
254 gboolean
255 rb_daap_mdns_publisher_withdraw (RBDaapMdnsPublisher *publisher,
256 GError **error)
258 if (publisher->priv->discovery == NULL) {
259 g_set_error (error,
260 RB_DAAP_MDNS_PUBLISHER_ERROR,
261 RB_DAAP_MDNS_PUBLISHER_ERROR_NOT_RUNNING,
262 "%s",
263 _("The howl MDNS service is not running"));
264 return FALSE;
267 if (publisher->priv->oid == NULL) {
268 g_set_error (error,
269 RB_DAAP_MDNS_PUBLISHER_ERROR,
270 RB_DAAP_MDNS_PUBLISHER_ERROR_FAILED,
271 "%s",
272 _("The MDNS service is not published"));
273 return FALSE;
276 sw_discovery_cancel (*publisher->priv->discovery, *publisher->priv->oid);
278 g_free (publisher->priv->oid);
279 publisher->priv->oid = NULL;
281 return TRUE;
284 gboolean
285 rb_daap_mdns_publisher_set_name (RBDaapMdnsPublisher *publisher,
286 const char *name,
287 GError **error)
289 g_return_val_if_fail (publisher != NULL, FALSE);
291 g_free (publisher->priv->name);
292 publisher->priv->name = g_strdup (name);
294 if (publisher->priv->oid) {
295 refresh_service (publisher, error);
298 return TRUE;
300 gboolean
301 rb_daap_mdns_publisher_set_port (RBDaapMdnsPublisher *publisher,
302 guint port,
303 GError **error)
305 g_return_val_if_fail (publisher != NULL, FALSE);
307 publisher->priv->port = port;
309 if (publisher->priv->oid) {
310 refresh_service (publisher, error);
313 return TRUE;
315 gboolean
316 rb_daap_mdns_publisher_set_password_required (RBDaapMdnsPublisher *publisher,
317 gboolean required,
318 GError **error)
320 g_return_val_if_fail (publisher != NULL, FALSE);
322 publisher->priv->password_required = required;
324 if (publisher->priv->oid) {
325 refresh_service (publisher, error);
328 return TRUE;
331 static void
332 rb_daap_mdns_publisher_set_property (GObject *object,
333 guint prop_id,
334 const GValue *value,
335 GParamSpec *pspec)
337 switch (prop_id) {
338 default:
339 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
340 break;
344 static void
345 rb_daap_mdns_publisher_get_property (GObject *object,
346 guint prop_id,
347 GValue *value,
348 GParamSpec *pspec)
350 switch (prop_id) {
351 default:
352 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
353 break;
357 static void
358 rb_daap_mdns_publisher_class_init (RBDaapMdnsPublisherClass *klass)
360 GObjectClass *object_class = G_OBJECT_CLASS (klass);
362 object_class->finalize = rb_daap_mdns_publisher_finalize;
363 object_class->get_property = rb_daap_mdns_publisher_get_property;
364 object_class->set_property = rb_daap_mdns_publisher_set_property;
366 signals [PUBLISHED] =
367 g_signal_new ("published",
368 G_TYPE_FROM_CLASS (object_class),
369 G_SIGNAL_RUN_LAST,
370 G_STRUCT_OFFSET (RBDaapMdnsPublisherClass, published),
371 NULL,
372 NULL,
373 g_cclosure_marshal_VOID__STRING,
374 G_TYPE_NONE,
375 1, G_TYPE_STRING);
376 signals [NAME_COLLISION] =
377 g_signal_new ("name-collision",
378 G_TYPE_FROM_CLASS (object_class),
379 G_SIGNAL_RUN_LAST,
380 G_STRUCT_OFFSET (RBDaapMdnsPublisherClass, name_collision),
381 NULL,
382 NULL,
383 g_cclosure_marshal_VOID__STRING,
384 G_TYPE_NONE,
385 1, G_TYPE_STRING);
387 g_type_class_add_private (klass, sizeof (RBDaapMdnsPublisherPrivate));
390 static void
391 rb_daap_mdns_publisher_init (RBDaapMdnsPublisher *publisher)
393 publisher->priv = RB_DAAP_MDNS_PUBLISHER_GET_PRIVATE (publisher);
395 howl_client_init (publisher);
398 static void
399 rb_daap_mdns_publisher_finalize (GObject *object)
401 RBDaapMdnsPublisher *publisher;
403 g_return_if_fail (object != NULL);
404 g_return_if_fail (RB_IS_DAAP_MDNS_PUBLISHER (object));
406 publisher = RB_DAAP_MDNS_PUBLISHER (object);
408 g_return_if_fail (publisher->priv != NULL);
410 if (publisher->priv->oid) {
411 rb_daap_mdns_publisher_withdraw (publisher, NULL);
414 if (publisher->priv->discovery) {
415 sw_discovery_fina (*publisher->priv->discovery);
416 g_free (publisher->priv->discovery);
419 if (publisher->priv->watch_id > 0) {
420 g_source_remove (publisher->priv->watch_id);
423 g_free (publisher->priv->name);
425 G_OBJECT_CLASS (rb_daap_mdns_publisher_parent_class)->finalize (object);
428 RBDaapMdnsPublisher *
429 rb_daap_mdns_publisher_new (void)
431 if (publisher_object) {
432 g_object_ref (publisher_object);
433 } else {
434 publisher_object = g_object_new (RB_TYPE_DAAP_MDNS_PUBLISHER, NULL);
435 g_object_add_weak_pointer (publisher_object,
436 (gpointer *) &publisher_object);
439 return RB_DAAP_MDNS_PUBLISHER (publisher_object);