2 This file is part of avahi.
4 avahi is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 avahi is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12 Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with avahi; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 #include <sys/types.h>
25 #include <sys/socket.h>
32 #include <avahi-glib/glib-watch.h>
33 #include <avahi-client/client.h>
34 #include <avahi-client/lookup.h>
35 #include <avahi-common/error.h>
36 #include <avahi-common/address.h>
37 #include <avahi-common/domain.h>
38 #include <avahi-common/i18n.h>
42 #if defined(HAVE_GDBM) || defined(HAVE_DBM)
43 #include "../avahi-utils/stdb.h"
46 /* todo: i18n, HIGify */
48 struct _AuiServiceDialogPrivate {
49 AvahiGLibPoll *glib_poll;
51 AvahiServiceBrowser **browsers;
52 AvahiServiceResolver *resolver;
53 AvahiDomainBrowser *domain_browser;
55 gchar **browse_service_types;
59 AvahiProtocol address_family;
63 AvahiStringList *txt_data;
66 gboolean resolve_service, resolve_service_done;
67 gboolean resolve_host_name, resolve_host_name_done;
69 GtkWidget *domain_label;
70 GtkWidget *domain_button;
71 GtkWidget *service_tree_view;
72 GtkWidget *service_progress_bar;
74 GtkListStore *service_list_store, *domain_list_store;
75 GHashTable *service_type_names;
77 guint service_pulse_timeout;
78 guint domain_pulse_timeout;
81 AvahiIfIndex common_interface;
82 AvahiProtocol common_protocol;
84 GtkWidget *domain_dialog;
85 GtkWidget *domain_entry;
86 GtkWidget *domain_tree_view;
87 GtkWidget *domain_progress_bar;
88 GtkWidget *domain_ok_button;
90 gint forward_response_id;
95 PROP_BROWSE_SERVICE_TYPES,
103 PROP_RESOLVE_SERVICE,
104 PROP_RESOLVE_HOST_NAME,
109 SERVICE_COLUMN_IFACE,
110 SERVICE_COLUMN_PROTO,
113 SERVICE_COLUMN_PRETTY_IFACE,
114 SERVICE_COLUMN_PRETTY_TYPE,
124 static void aui_service_dialog_finalize(GObject *object);
125 static void aui_service_dialog_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
126 static void aui_service_dialog_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
128 static int get_default_response(GtkDialog *dlg) {
129 gint ret = GTK_RESPONSE_NONE;
131 if (gtk_window_get_default_widget(GTK_WINDOW(dlg)))
132 /* Use the response of the default widget, if possible */
133 ret = gtk_dialog_get_response_for_widget(dlg, gtk_window_get_default_widget(GTK_WINDOW(dlg)));
135 if (ret == GTK_RESPONSE_NONE) {
136 /* Fall back to finding the first positive response */
138 gint bad = GTK_RESPONSE_NONE;
140 t = children = gtk_container_get_children(GTK_CONTAINER(gtk_dialog_get_action_area(dlg)));
143 GtkWidget *child = t->data;
145 ret = gtk_dialog_get_response_for_widget(dlg, child);
147 if (ret == GTK_RESPONSE_ACCEPT ||
148 ret == GTK_RESPONSE_OK ||
149 ret == GTK_RESPONSE_YES ||
150 ret == GTK_RESPONSE_APPLY)
153 if (ret != GTK_RESPONSE_NONE && bad == GTK_RESPONSE_NONE)
159 g_list_free (children);
161 /* Fall back to finding the first negative response */
162 if (ret == GTK_RESPONSE_NONE)
169 G_DEFINE_TYPE(AuiServiceDialog, aui_service_dialog, GTK_TYPE_DIALOG)
171 static void aui_service_dialog_class_init(AuiServiceDialogClass *klass) {
172 GObjectClass *object_class;
176 object_class = (GObjectClass*) klass;
178 object_class->finalize = aui_service_dialog_finalize;
179 object_class->set_property = aui_service_dialog_set_property;
180 object_class->get_property = aui_service_dialog_get_property;
182 g_object_class_install_property(
184 PROP_BROWSE_SERVICE_TYPES,
185 g_param_spec_pointer("browse_service_types", _("Browse Service Types"), _("A NULL terminated list of service types to browse for"),
186 G_PARAM_READABLE | G_PARAM_WRITABLE));
187 g_object_class_install_property(
190 g_param_spec_string("domain", _("Domain"), _("The domain to browse in, or NULL for the default domain"),
192 G_PARAM_READABLE | G_PARAM_WRITABLE));
193 g_object_class_install_property(
196 g_param_spec_string("service_type", _("Service Type"), _("The service type of the selected service"),
198 G_PARAM_READABLE | G_PARAM_WRITABLE));
199 g_object_class_install_property(
202 g_param_spec_string("service_name", _("Service Name"), _("The service name of the selected service"),
204 G_PARAM_READABLE | G_PARAM_WRITABLE));
205 g_object_class_install_property(
208 g_param_spec_pointer("address", _("Address"), _("The address of the resolved service"),
210 g_object_class_install_property(
213 g_param_spec_uint("port", _("Port"), _("The IP port number of the resolved service"),
216 g_object_class_install_property(
219 g_param_spec_string("host_name", _("Host Name"), _("The host name of the resolved service"),
222 g_object_class_install_property(
225 g_param_spec_pointer("txt_data", _("TXT Data"), _("The TXT data of the resolved service"),
227 g_object_class_install_property(
229 PROP_RESOLVE_SERVICE,
230 g_param_spec_boolean("resolve_service", _("Resolve service"), _("Resolve service"),
232 G_PARAM_READABLE | G_PARAM_WRITABLE));
233 g_object_class_install_property(
235 PROP_RESOLVE_HOST_NAME,
236 g_param_spec_boolean("resolve_host_name", _("Resolve service host name"), _("Resolve service host name"),
238 G_PARAM_READABLE | G_PARAM_WRITABLE));
239 g_object_class_install_property(
242 g_param_spec_int("address_family", _("Address family"), _("The address family for host name resolution"),
243 AVAHI_PROTO_UNSPEC, AVAHI_PROTO_INET6, AVAHI_PROTO_UNSPEC,
244 G_PARAM_READABLE | G_PARAM_WRITABLE));
248 GtkWidget *aui_service_dialog_new_valist(
251 const gchar *first_button_text,
254 const gchar *button_text;
257 GtkWidget *w = GTK_WIDGET(g_object_new(
258 AUI_TYPE_SERVICE_DIALOG,
259 "has-separator", FALSE,
264 gtk_window_set_transient_for(GTK_WINDOW(w), parent);
266 button_text = first_button_text;
267 while (button_text) {
270 response_id = va_arg(varargs, gint);
271 gtk_dialog_add_button(GTK_DIALOG(w), button_text, response_id);
272 button_text = va_arg(varargs, const gchar *);
275 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_ACCEPT, FALSE);
276 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_OK, FALSE);
277 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_YES, FALSE);
278 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_APPLY, FALSE);
280 if ((dr = get_default_response(GTK_DIALOG(w))) != GTK_RESPONSE_NONE)
281 gtk_dialog_set_default_response(GTK_DIALOG(w), dr);
286 GtkWidget* aui_service_dialog_new(
289 const gchar *first_button_text,
295 va_start(varargs, first_button_text);
296 w = aui_service_dialog_new_valist(title, parent, first_button_text, varargs);
302 static gboolean service_pulse_callback(gpointer data) {
303 AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
305 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->priv->service_progress_bar));
309 static gboolean domain_pulse_callback(gpointer data) {
310 AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
312 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->priv->domain_progress_bar));
316 static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
317 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
319 if (state == AVAHI_CLIENT_FAILURE) {
320 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
321 GTK_DIALOG_DESTROY_WITH_PARENT,
324 _("Avahi client failure: %s"),
325 avahi_strerror(avahi_client_errno(c)));
326 gtk_dialog_run(GTK_DIALOG(m));
327 gtk_widget_destroy(m);
329 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
333 static void resolve_callback(
334 AvahiServiceResolver *r G_GNUC_UNUSED,
335 AvahiIfIndex interface G_GNUC_UNUSED,
336 AvahiProtocol protocol G_GNUC_UNUSED,
337 AvahiResolverEvent event,
341 const char *host_name,
342 const AvahiAddress *a,
344 AvahiStringList *txt,
345 AvahiLookupResultFlags flags G_GNUC_UNUSED,
348 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
351 case AVAHI_RESOLVER_FOUND:
353 d->priv->resolve_service_done = 1;
355 g_free(d->priv->service_name);
356 d->priv->service_name = g_strdup(name);
358 g_free(d->priv->service_type);
359 d->priv->service_type = g_strdup(type);
361 g_free(d->priv->domain);
362 d->priv->domain = g_strdup(domain);
364 g_free(d->priv->host_name);
365 d->priv->host_name = g_strdup(host_name);
367 d->priv->port = port;
369 avahi_string_list_free(d->priv->txt_data);
370 d->priv->txt_data = avahi_string_list_copy(txt);
373 d->priv->resolve_host_name_done = 1;
374 d->priv->address = *a;
377 gtk_dialog_response(GTK_DIALOG(d), d->priv->forward_response_id);
381 case AVAHI_RESOLVER_FAILURE: {
382 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
383 GTK_DIALOG_DESTROY_WITH_PARENT,
386 _("Avahi resolver failure: %s"),
387 avahi_strerror(avahi_client_errno(d->priv->client)));
388 gtk_dialog_run(GTK_DIALOG(m));
389 gtk_widget_destroy(m);
391 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
398 static void browse_callback(
399 AvahiServiceBrowser *b G_GNUC_UNUSED,
400 AvahiIfIndex interface,
401 AvahiProtocol protocol,
402 AvahiBrowserEvent event,
406 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
409 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
413 case AVAHI_BROWSER_NEW: {
415 const gchar *pretty_type = NULL;
416 char ifname[IFNAMSIZ];
418 GtkTreeSelection *selection;
420 if (!(if_indextoname(interface, ifname)))
421 g_snprintf(ifname, sizeof(ifname), "%i", interface);
423 ifs = g_strdup_printf("%s %s", ifname, protocol == AVAHI_PROTO_INET ? "IPv4" : "IPv6");
425 if (d->priv->service_type_names)
426 pretty_type = g_hash_table_lookup (d->priv->service_type_names, type);
429 #if defined(HAVE_GDBM) || defined(HAVE_DBM)
430 pretty_type = stdb_lookup(type);
436 gtk_list_store_append(d->priv->service_list_store, &iter);
438 gtk_list_store_set(d->priv->service_list_store, &iter,
439 SERVICE_COLUMN_IFACE, interface,
440 SERVICE_COLUMN_PROTO, protocol,
441 SERVICE_COLUMN_NAME, name,
442 SERVICE_COLUMN_TYPE, type,
443 SERVICE_COLUMN_PRETTY_IFACE, ifs,
444 SERVICE_COLUMN_PRETTY_TYPE, pretty_type,
449 if (d->priv->common_protocol == AVAHI_PROTO_UNSPEC)
450 d->priv->common_protocol = protocol;
452 if (d->priv->common_interface == AVAHI_IF_UNSPEC)
453 d->priv->common_interface = interface;
455 if (d->priv->common_interface != interface || d->priv->common_protocol != protocol) {
456 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 0), TRUE);
457 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), TRUE);
460 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->service_tree_view));
461 if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) {
463 if (!d->priv->service_type ||
464 !d->priv->service_name ||
465 (avahi_domain_equal(d->priv->service_type, type) && strcasecmp(d->priv->service_name, name) == 0)) {
468 gtk_tree_selection_select_iter(selection, &iter);
470 path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
471 gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->priv->service_tree_view), path, NULL, FALSE);
472 gtk_tree_path_free(path);
480 case AVAHI_BROWSER_REMOVE: {
484 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
486 gint _interface, _protocol;
487 gchar *_name, *_type;
490 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->service_list_store), &iter,
491 SERVICE_COLUMN_IFACE, &_interface,
492 SERVICE_COLUMN_PROTO, &_protocol,
493 SERVICE_COLUMN_NAME, &_name,
494 SERVICE_COLUMN_TYPE, &_type,
497 found = _interface == interface && _protocol == protocol && strcasecmp(_name, name) == 0 && avahi_domain_equal(_type, type);
501 gtk_list_store_remove(d->priv->service_list_store, &iter);
505 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
511 case AVAHI_BROWSER_FAILURE: {
512 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
513 GTK_DIALOG_DESTROY_WITH_PARENT,
516 _("Browsing for service type %s in domain %s failed: %s"),
517 type, domain ? domain : _("n/a"),
518 avahi_strerror(avahi_client_errno(d->priv->client)));
519 gtk_dialog_run(GTK_DIALOG(m));
520 gtk_widget_destroy(m);
525 case AVAHI_BROWSER_ALL_FOR_NOW:
526 if (d->priv->service_pulse_timeout > 0) {
527 g_source_remove(d->priv->service_pulse_timeout);
528 d->priv->service_pulse_timeout = 0;
529 gtk_widget_hide(d->priv->service_progress_bar);
533 case AVAHI_BROWSER_CACHE_EXHAUSTED:
538 static void domain_make_default_selection(AuiServiceDialog *d, const gchar *name, GtkTreeIter *iter) {
539 GtkTreeSelection *selection;
541 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->domain_tree_view));
542 if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) {
544 if (avahi_domain_equal(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry)), name)) {
547 gtk_tree_selection_select_iter(selection, iter);
549 path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->priv->domain_list_store), iter);
550 gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->priv->domain_tree_view), path, NULL, FALSE);
551 gtk_tree_path_free(path);
557 static void domain_browse_callback(
558 AvahiDomainBrowser *b G_GNUC_UNUSED,
559 AvahiIfIndex interface G_GNUC_UNUSED,
560 AvahiProtocol protocol G_GNUC_UNUSED,
561 AvahiBrowserEvent event,
563 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
566 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
570 case AVAHI_BROWSER_NEW: {
572 gboolean found = FALSE, valid;
575 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
579 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
580 DOMAIN_COLUMN_NAME, &_name,
581 DOMAIN_COLUMN_REF, &ref,
584 found = avahi_domain_equal(_name, name);
590 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
594 gtk_list_store_set(d->priv->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref + 1, -1);
596 gtk_list_store_append(d->priv->domain_list_store, &iter);
598 gtk_list_store_set(d->priv->domain_list_store, &iter,
599 DOMAIN_COLUMN_NAME, name,
600 DOMAIN_COLUMN_REF, 1,
604 domain_make_default_selection(d, name, &iter);
609 case AVAHI_BROWSER_REMOVE: {
613 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
619 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
620 DOMAIN_COLUMN_NAME, &_name,
621 DOMAIN_COLUMN_REF, &ref,
624 found = avahi_domain_equal(_name, name);
629 gtk_list_store_remove(d->priv->service_list_store, &iter);
631 gtk_list_store_set(d->priv->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref - 1, -1);
635 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
642 case AVAHI_BROWSER_FAILURE: {
643 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
644 GTK_DIALOG_DESTROY_WITH_PARENT,
647 _("Avahi domain browser failure: %s"),
648 avahi_strerror(avahi_client_errno(d->priv->client)));
649 gtk_dialog_run(GTK_DIALOG(m));
650 gtk_widget_destroy(m);
655 case AVAHI_BROWSER_ALL_FOR_NOW:
656 if (d->priv->domain_pulse_timeout > 0) {
657 g_source_remove(d->priv->domain_pulse_timeout);
658 d->priv->domain_pulse_timeout = 0;
659 gtk_widget_hide(d->priv->domain_progress_bar);
663 case AVAHI_BROWSER_CACHE_EXHAUSTED:
668 static const gchar *get_domain_name(AuiServiceDialog *d) {
671 g_return_val_if_fail(d, NULL);
672 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
675 return d->priv->domain;
677 if (!(domain = avahi_client_get_domain_name(d->priv->client))) {
678 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
679 GTK_DIALOG_DESTROY_WITH_PARENT,
682 _("Failed to read Avahi domain: %s"),
683 avahi_strerror(avahi_client_errno(d->priv->client)));
684 gtk_dialog_run(GTK_DIALOG(m));
685 gtk_widget_destroy(m);
693 static gboolean start_callback(gpointer data) {
695 AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
697 AvahiServiceBrowser **sb;
701 d->priv->start_idle = 0;
703 if (!d->priv->browse_service_types || !*d->priv->browse_service_types) {
704 g_warning(_("Browse service type list is empty!"));
708 if (!d->priv->client) {
709 if (!(d->priv->client = avahi_client_new(avahi_glib_poll_get(d->priv->glib_poll), 0, client_callback, d, &error))) {
711 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
712 GTK_DIALOG_DESTROY_WITH_PARENT,
715 _("Failed to connect to Avahi server: %s"),
716 avahi_strerror(error));
717 gtk_dialog_run(GTK_DIALOG(m));
718 gtk_widget_destroy(m);
720 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
725 if (!(domain = get_domain_name(d))) {
726 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
732 if (avahi_domain_equal(domain, "local."))
733 gtk_label_set_markup(GTK_LABEL(d->priv->domain_label), _("Browsing for services on <b>local network</b>:"));
735 gchar *t = g_strdup_printf(_("Browsing for services in domain <b>%s</b>:"), domain);
736 gtk_label_set_markup(GTK_LABEL(d->priv->domain_label), t);
740 if (d->priv->browsers) {
741 for (sb = d->priv->browsers; *sb; sb++)
742 avahi_service_browser_free(*sb);
744 g_free(d->priv->browsers);
745 d->priv->browsers = NULL;
748 gtk_list_store_clear(GTK_LIST_STORE(d->priv->service_list_store));
749 d->priv->common_interface = AVAHI_IF_UNSPEC;
750 d->priv->common_protocol = AVAHI_PROTO_UNSPEC;
752 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 0), FALSE);
753 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), FALSE);
754 gtk_widget_show(d->priv->service_progress_bar);
756 if (d->priv->service_pulse_timeout <= 0)
757 d->priv->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
759 for (i = 0; d->priv->browse_service_types[i]; i++)
763 d->priv->browsers = g_new0(AvahiServiceBrowser*, i+1);
764 for (st = d->priv->browse_service_types, sb = d->priv->browsers; *st; st++, sb++) {
766 if (!(*sb = avahi_service_browser_new(d->priv->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, *st, d->priv->domain, 0, browse_callback, d))) {
767 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
768 GTK_DIALOG_DESTROY_WITH_PARENT,
771 _("Failed to create browser for %s: %s"),
773 avahi_strerror(avahi_client_errno(d->priv->client)));
774 gtk_dialog_run(GTK_DIALOG(m));
775 gtk_widget_destroy(m);
777 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
786 static void aui_service_dialog_finalize(GObject *object) {
787 AuiServiceDialog *d = AUI_SERVICE_DIALOG(object);
789 if (d->priv->domain_pulse_timeout > 0)
790 g_source_remove(d->priv->domain_pulse_timeout);
792 if (d->priv->service_pulse_timeout > 0)
793 g_source_remove(d->priv->service_pulse_timeout);
795 if (d->priv->start_idle > 0)
796 g_source_remove(d->priv->start_idle);
798 g_free(d->priv->host_name);
799 g_free(d->priv->domain);
800 g_free(d->priv->service_name);
802 avahi_string_list_free(d->priv->txt_data);
804 g_strfreev(d->priv->browse_service_types);
806 if (d->priv->domain_browser)
807 avahi_domain_browser_free(d->priv->domain_browser);
809 if (d->priv->resolver)
810 avahi_service_resolver_free(d->priv->resolver);
812 if (d->priv->browsers) {
813 AvahiServiceBrowser **sb;
815 for (sb = d->priv->browsers; *sb; sb++)
816 avahi_service_browser_free(*sb);
818 g_free(d->priv->browsers);
822 avahi_client_free(d->priv->client);
824 if (d->priv->glib_poll)
825 avahi_glib_poll_free(d->priv->glib_poll);
827 if (d->priv->service_list_store)
828 g_object_unref(d->priv->service_list_store);
829 if (d->priv->domain_list_store)
830 g_object_unref(d->priv->domain_list_store);
831 if (d->priv->service_type_names)
832 g_hash_table_unref (d->priv->service_type_names);
837 G_OBJECT_CLASS(aui_service_dialog_parent_class)->finalize(object);
840 static void service_row_activated_callback(GtkTreeView *tree_view G_GNUC_UNUSED, GtkTreePath *path G_GNUC_UNUSED, GtkTreeViewColumn *column G_GNUC_UNUSED, gpointer user_data) {
841 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
843 gtk_dialog_response(GTK_DIALOG(d), get_default_response(GTK_DIALOG(d)));
846 static void service_selection_changed_callback(GtkTreeSelection *selection, gpointer user_data) {
847 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
850 b = gtk_tree_selection_get_selected(selection, NULL, NULL);
851 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT, b);
852 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_OK, b);
853 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_YES, b);
854 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_APPLY, b);
857 static void response_callback(GtkDialog *dialog, gint response, gpointer user_data) {
858 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
860 if ((response == GTK_RESPONSE_ACCEPT ||
861 response == GTK_RESPONSE_OK ||
862 response == GTK_RESPONSE_YES ||
863 response == GTK_RESPONSE_APPLY) &&
864 ((d->priv->resolve_service && !d->priv->resolve_service_done) ||
865 (d->priv->resolve_host_name && !d->priv->resolve_host_name_done))) {
868 gint interface, protocol;
872 g_signal_stop_emission(dialog, g_signal_lookup("response", gtk_dialog_get_type()), 0);
873 d->priv->forward_response_id = response;
875 if (d->priv->resolver)
878 g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->service_tree_view)), NULL, &iter));
880 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->service_list_store), &iter,
881 SERVICE_COLUMN_IFACE, &interface,
882 SERVICE_COLUMN_PROTO, &protocol,
883 SERVICE_COLUMN_NAME, &name,
884 SERVICE_COLUMN_TYPE, &type, -1);
886 g_return_if_fail(d->priv->client);
888 gtk_widget_set_sensitive(GTK_WIDGET(dialog), FALSE);
889 cursor = gdk_cursor_new(GDK_WATCH);
890 gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(dialog)), cursor);
891 gdk_cursor_unref(cursor);
893 if (!(d->priv->resolver = avahi_service_resolver_new(
894 d->priv->client, interface, protocol, name, type, d->priv->domain,
895 d->priv->address_family, !d->priv->resolve_host_name ? AVAHI_LOOKUP_NO_ADDRESS : 0, resolve_callback, d))) {
897 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
898 GTK_DIALOG_DESTROY_WITH_PARENT,
901 _("Failed to create resolver for %s of type %s in domain %s: %s"),
902 name, type, d->priv->domain,
903 avahi_strerror(avahi_client_errno(d->priv->client)));
904 gtk_dialog_run(GTK_DIALOG(m));
905 gtk_widget_destroy(m);
907 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
913 static gboolean is_valid_domain_suffix(const gchar *n) {
914 gchar label[AVAHI_LABEL_MAX];
916 if (!avahi_is_valid_domain_name(n))
919 if (!avahi_unescape_label(&n, label, sizeof(label)))
922 /* At least one label */
927 static void domain_row_activated_callback(GtkTreeView *tree_view G_GNUC_UNUSED, GtkTreePath *path G_GNUC_UNUSED, GtkTreeViewColumn *column G_GNUC_UNUSED, gpointer user_data) {
928 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
930 if (is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry))))
931 gtk_dialog_response(GTK_DIALOG(d->priv->domain_dialog), GTK_RESPONSE_ACCEPT);
934 static void domain_selection_changed_callback(GtkTreeSelection *selection G_GNUC_UNUSED, gpointer user_data) {
936 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
939 g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->domain_tree_view)), NULL, &iter));
941 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
942 DOMAIN_COLUMN_NAME, &name, -1);
944 gtk_entry_set_text(GTK_ENTRY(d->priv->domain_entry), name);
947 static void domain_entry_changed_callback(GtkEditable *editable G_GNUC_UNUSED, gpointer user_data) {
948 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
950 gtk_widget_set_sensitive(d->priv->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry))));
953 static void domain_button_clicked(GtkButton *button G_GNUC_UNUSED, gpointer user_data) {
954 GtkWidget *vbox, *vbox2, *scrolled_window;
955 GtkTreeSelection *selection;
956 GtkCellRenderer *renderer;
957 GtkTreeViewColumn *column;
958 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
959 AuiServiceDialogPrivate *p = d->priv;
963 g_return_if_fail(!p->domain_dialog);
964 g_return_if_fail(!p->domain_browser);
966 if (!(domain = get_domain_name(d))) {
967 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
971 if (!(p->domain_browser = avahi_domain_browser_new(p->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DOMAIN_BROWSER_BROWSE, 0, domain_browse_callback, d))) {
972 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
973 GTK_DIALOG_DESTROY_WITH_PARENT,
976 _("Failed to create domain browser: %s"),
977 avahi_strerror(avahi_client_errno(p->client)));
978 gtk_dialog_run(GTK_DIALOG(m));
979 gtk_widget_destroy(m);
981 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
985 p->domain_dialog = gtk_dialog_new();
986 gtk_container_set_border_width(GTK_CONTAINER(p->domain_dialog), 5);
987 gtk_window_set_title(GTK_WINDOW(p->domain_dialog), _("Change domain"));
988 gtk_dialog_set_has_separator(GTK_DIALOG(p->domain_dialog), FALSE);
990 vbox = gtk_vbox_new(FALSE, 8);
991 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
992 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(p->domain_dialog))), vbox, TRUE, TRUE, 0);
994 p->domain_entry = gtk_entry_new();
995 gtk_entry_set_max_length(GTK_ENTRY(p->domain_entry), AVAHI_DOMAIN_NAME_MAX);
996 gtk_entry_set_text(GTK_ENTRY(p->domain_entry), domain);
997 gtk_entry_set_activates_default(GTK_ENTRY(p->domain_entry), TRUE);
998 g_signal_connect(p->domain_entry, "changed", G_CALLBACK(domain_entry_changed_callback), d);
999 gtk_box_pack_start(GTK_BOX(vbox), p->domain_entry, FALSE, FALSE, 0);
1001 vbox2 = gtk_vbox_new(FALSE, 8);
1002 gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
1004 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1005 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1006 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
1007 gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0);
1009 p->domain_list_store = gtk_list_store_new(N_DOMAIN_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
1011 p->domain_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p->domain_list_store));
1012 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(p->domain_tree_view), FALSE);
1013 g_signal_connect(p->domain_tree_view, "row-activated", G_CALLBACK(domain_row_activated_callback), d);
1014 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(p->domain_tree_view));
1015 gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
1016 g_signal_connect(selection, "changed", G_CALLBACK(domain_selection_changed_callback), d);
1018 renderer = gtk_cell_renderer_text_new();
1019 column = gtk_tree_view_column_new_with_attributes(_("Service Name"), renderer, "text", DOMAIN_COLUMN_NAME, NULL);
1020 gtk_tree_view_column_set_expand(column, TRUE);
1021 gtk_tree_view_append_column(GTK_TREE_VIEW(p->domain_tree_view), column);
1023 gtk_tree_view_set_search_column(GTK_TREE_VIEW(p->domain_tree_view), DOMAIN_COLUMN_NAME);
1024 gtk_container_add(GTK_CONTAINER(scrolled_window), p->domain_tree_view);
1026 p->domain_progress_bar = gtk_progress_bar_new();
1027 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(p->domain_progress_bar), _("Browsing..."));
1028 gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(p->domain_progress_bar), 0.1);
1029 gtk_box_pack_end(GTK_BOX(vbox2), p->domain_progress_bar, FALSE, FALSE, 0);
1031 gtk_dialog_add_button(GTK_DIALOG(p->domain_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1032 p->domain_ok_button = GTK_WIDGET(gtk_dialog_add_button(GTK_DIALOG(p->domain_dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT));
1033 gtk_dialog_set_default_response(GTK_DIALOG(p->domain_dialog), GTK_RESPONSE_ACCEPT);
1034 gtk_widget_set_sensitive(p->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(p->domain_entry))));
1036 gtk_widget_grab_default(p->domain_ok_button);
1037 gtk_widget_grab_focus(p->domain_entry);
1039 gtk_window_set_default_size(GTK_WINDOW(p->domain_dialog), 300, 300);
1041 gtk_widget_show_all(vbox);
1043 gtk_list_store_append(p->domain_list_store, &iter);
1044 gtk_list_store_set(p->domain_list_store, &iter, DOMAIN_COLUMN_NAME, "local", DOMAIN_COLUMN_REF, 1, -1);
1045 domain_make_default_selection(d, "local", &iter);
1047 p->domain_pulse_timeout = g_timeout_add(100, domain_pulse_callback, d);
1049 if (gtk_dialog_run(GTK_DIALOG(p->domain_dialog)) == GTK_RESPONSE_ACCEPT)
1050 aui_service_dialog_set_domain(d, gtk_entry_get_text(GTK_ENTRY(p->domain_entry)));
1052 gtk_widget_destroy(p->domain_dialog);
1053 p->domain_dialog = NULL;
1055 if (p->domain_pulse_timeout > 0) {
1056 g_source_remove(p->domain_pulse_timeout);
1057 p->domain_pulse_timeout = 0;
1060 avahi_domain_browser_free(p->domain_browser);
1061 p->domain_browser = NULL;
1064 static void aui_service_dialog_init(AuiServiceDialog *d) {
1065 GtkWidget *vbox, *vbox2, *scrolled_window;
1066 GtkCellRenderer *renderer;
1067 GtkTreeViewColumn *column;
1068 GtkTreeSelection *selection;
1069 AuiServiceDialogPrivate *p;
1071 p = d->priv = g_new(AuiServiceDialogPrivate, 1);
1073 p->host_name = NULL;
1075 p->service_name = NULL;
1076 p->service_type = NULL;
1078 p->browse_service_types = NULL;
1079 memset(&p->address, 0, sizeof(p->address));
1081 p->resolve_host_name = p->resolve_service = TRUE;
1082 p->resolve_host_name_done = p->resolve_service_done = FALSE;
1083 p->address_family = AVAHI_PROTO_UNSPEC;
1085 p->glib_poll = NULL;
1089 p->domain_browser = NULL;
1091 p->service_pulse_timeout = 0;
1092 p->domain_pulse_timeout = 0;
1094 p->common_interface = AVAHI_IF_UNSPEC;
1095 p->common_protocol = AVAHI_PROTO_UNSPEC;
1097 p->domain_dialog = NULL;
1098 p->domain_entry = NULL;
1099 p->domain_tree_view = NULL;
1100 p->domain_progress_bar = NULL;
1101 p->domain_ok_button = NULL;
1103 p->forward_response_id = GTK_RESPONSE_NONE;
1105 p->service_list_store = p->domain_list_store = NULL;
1106 p->service_type_names = NULL;
1108 gtk_widget_push_composite_child();
1110 gtk_container_set_border_width(GTK_CONTAINER(d), 5);
1112 vbox = gtk_vbox_new(FALSE, 8);
1113 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
1114 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(d))), vbox, TRUE, TRUE, 0);
1116 p->domain_label = gtk_label_new(_("Initializing..."));
1117 gtk_label_set_ellipsize(GTK_LABEL(p->domain_label), TRUE);
1118 gtk_misc_set_alignment(GTK_MISC(p->domain_label), 0, 0.5);
1119 gtk_box_pack_start(GTK_BOX(vbox), p->domain_label, FALSE, FALSE, 0);
1122 vbox2 = gtk_vbox_new(FALSE, 8);
1123 gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
1125 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1126 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1127 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
1128 gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0);
1130 p->service_list_store = gtk_list_store_new(N_SERVICE_COLUMNS, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1132 p->service_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p->service_list_store));
1133 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(p->service_tree_view), FALSE);
1134 g_signal_connect(p->service_tree_view, "row-activated", G_CALLBACK(service_row_activated_callback), d);
1135 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(p->service_tree_view));
1136 gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
1137 g_signal_connect(selection, "changed", G_CALLBACK(service_selection_changed_callback), d);
1139 renderer = gtk_cell_renderer_text_new();
1140 column = gtk_tree_view_column_new_with_attributes(_("Location"), renderer, "text", SERVICE_COLUMN_PRETTY_IFACE, NULL);
1141 gtk_tree_view_column_set_visible(column, FALSE);
1142 gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
1144 renderer = gtk_cell_renderer_text_new();
1145 column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", SERVICE_COLUMN_NAME, NULL);
1146 gtk_tree_view_column_set_expand(column, TRUE);
1147 gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
1149 renderer = gtk_cell_renderer_text_new();
1150 column = gtk_tree_view_column_new_with_attributes(_("Type"), renderer, "text", SERVICE_COLUMN_PRETTY_TYPE, NULL);
1151 gtk_tree_view_column_set_visible(column, FALSE);
1152 gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
1154 gtk_tree_view_set_search_column(GTK_TREE_VIEW(p->service_tree_view), SERVICE_COLUMN_NAME);
1155 gtk_container_add(GTK_CONTAINER(scrolled_window), p->service_tree_view);
1157 p->service_progress_bar = gtk_progress_bar_new();
1158 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(p->service_progress_bar), _("Browsing..."));
1159 gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(p->service_progress_bar), 0.1);
1160 gtk_box_pack_end(GTK_BOX(vbox2), p->service_progress_bar, FALSE, FALSE, 0);
1162 p->domain_button = gtk_button_new_with_mnemonic(_("_Domain..."));
1163 gtk_button_set_image(GTK_BUTTON(p->domain_button), gtk_image_new_from_stock(GTK_STOCK_NETWORK, GTK_ICON_SIZE_BUTTON));
1164 g_signal_connect(p->domain_button, "clicked", G_CALLBACK(domain_button_clicked), d);
1165 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(d))), p->domain_button, FALSE, TRUE, 0);
1166 gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(gtk_dialog_get_action_area(GTK_DIALOG(d))), p->domain_button, TRUE);
1167 gtk_widget_show(p->domain_button);
1169 gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT);
1171 gtk_widget_grab_focus(p->service_tree_view);
1173 gtk_window_set_default_size(GTK_WINDOW(d), 400, 300);
1175 gtk_widget_show_all(vbox);
1177 gtk_widget_pop_composite_child();
1179 p->glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
1181 p->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
1182 p->start_idle = g_idle_add(start_callback, d);
1184 g_signal_connect(d, "response", G_CALLBACK(response_callback), d);
1187 static void restart_browsing(AuiServiceDialog *d) {
1188 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1190 if (d->priv->start_idle <= 0)
1191 d->priv->start_idle = g_idle_add(start_callback, d);
1194 void aui_service_dialog_set_browse_service_types(AuiServiceDialog *d, const char *type, ...) {
1199 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1200 g_return_if_fail(type);
1202 g_strfreev(d->priv->browse_service_types);
1205 for (u = 1; va_arg(ap, const char *); u++)
1209 d->priv->browse_service_types = g_new0(gchar*, u+1);
1210 d->priv->browse_service_types[0] = g_strdup(type);
1213 for (u = 1; (t = va_arg(ap, const char*)); u++)
1214 d->priv->browse_service_types[u] = g_strdup(t);
1217 if (d->priv->browse_service_types[0] && d->priv->browse_service_types[1]) {
1218 /* Multiple service types, show type-column */
1219 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 2), TRUE);
1222 restart_browsing(d);
1225 void aui_service_dialog_set_browse_service_typesv(AuiServiceDialog *d, const char *const*types) {
1227 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1228 g_return_if_fail(types);
1229 g_return_if_fail(*types);
1231 g_strfreev(d->priv->browse_service_types);
1232 d->priv->browse_service_types = g_strdupv((char**) types);
1234 if (d->priv->browse_service_types[0] && d->priv->browse_service_types[1]) {
1235 /* Multiple service types, show type-column */
1236 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 2), TRUE);
1239 restart_browsing(d);
1242 const gchar*const* aui_service_dialog_get_browse_service_types(AuiServiceDialog *d) {
1243 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1245 return (const char* const*) d->priv->browse_service_types;
1248 void aui_service_dialog_set_service_type_name(AuiServiceDialog *d, const gchar *type, const gchar *name) {
1249 GtkTreeModel *m = NULL;
1252 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1253 g_return_if_fail(NULL != type);
1254 g_return_if_fail(NULL != name);
1256 if (NULL == d->priv->service_type_names)
1257 d->priv->service_type_names = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1259 g_hash_table_insert(d->priv->service_type_names, g_strdup(type), g_strdup(name));
1261 if (d->priv->service_list_store)
1262 m = GTK_TREE_MODEL(d->priv->service_list_store);
1264 if (m && gtk_tree_model_get_iter_first(m, &iter)) {
1266 char *stored_type = NULL;
1268 gtk_tree_model_get(m, &iter, SERVICE_COLUMN_TYPE, &stored_type, -1);
1270 if (stored_type && g_str_equal(stored_type, type))
1271 gtk_list_store_set(d->priv->service_list_store, &iter, SERVICE_COLUMN_PRETTY_TYPE, name, -1);
1272 } while (gtk_tree_model_iter_next(m, &iter));
1276 void aui_service_dialog_set_domain(AuiServiceDialog *d, const char *domain) {
1277 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1278 g_return_if_fail(!domain || is_valid_domain_suffix(domain));
1280 g_free(d->priv->domain);
1281 d->priv->domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
1283 restart_browsing(d);
1286 const char* aui_service_dialog_get_domain(AuiServiceDialog *d) {
1287 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1289 return d->priv->domain;
1292 void aui_service_dialog_set_service_name(AuiServiceDialog *d, const char *name) {
1293 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1295 g_free(d->priv->service_name);
1296 d->priv->service_name = g_strdup(name);
1299 const char* aui_service_dialog_get_service_name(AuiServiceDialog *d) {
1300 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1302 return d->priv->service_name;
1305 void aui_service_dialog_set_service_type(AuiServiceDialog *d, const char*stype) {
1306 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1308 g_free(d->priv->service_type);
1309 d->priv->service_type = g_strdup(stype);
1312 const char* aui_service_dialog_get_service_type(AuiServiceDialog *d) {
1313 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1315 return d->priv->service_type;
1318 const AvahiAddress* aui_service_dialog_get_address(AuiServiceDialog *d) {
1319 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1320 g_return_val_if_fail(d->priv->resolve_service_done && d->priv->resolve_host_name_done, NULL);
1322 return &d->priv->address;
1325 guint16 aui_service_dialog_get_port(AuiServiceDialog *d) {
1326 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), 0);
1327 g_return_val_if_fail(d->priv->resolve_service_done, 0);
1329 return d->priv->port;
1332 const char* aui_service_dialog_get_host_name(AuiServiceDialog *d) {
1333 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1334 g_return_val_if_fail(d->priv->resolve_service_done, NULL);
1336 return d->priv->host_name;
1339 const AvahiStringList *aui_service_dialog_get_txt_data(AuiServiceDialog *d) {
1340 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1341 g_return_val_if_fail(d->priv->resolve_service_done, NULL);
1343 return d->priv->txt_data;
1346 void aui_service_dialog_set_resolve_service(AuiServiceDialog *d, gboolean resolve) {
1347 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1349 d->priv->resolve_service = resolve;
1352 gboolean aui_service_dialog_get_resolve_service(AuiServiceDialog *d) {
1353 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), FALSE);
1355 return d->priv->resolve_service;
1358 void aui_service_dialog_set_resolve_host_name(AuiServiceDialog *d, gboolean resolve) {
1359 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1361 d->priv->resolve_host_name = resolve;
1364 gboolean aui_service_dialog_get_resolve_host_name(AuiServiceDialog *d) {
1365 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), FALSE);
1367 return d->priv->resolve_host_name;
1370 void aui_service_dialog_set_address_family(AuiServiceDialog *d, AvahiProtocol proto) {
1371 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1372 g_return_if_fail(proto == AVAHI_PROTO_UNSPEC || proto == AVAHI_PROTO_INET || proto == AVAHI_PROTO_INET6);
1374 d->priv->address_family = proto;
1377 AvahiProtocol aui_service_dialog_get_address_family(AuiServiceDialog *d) {
1378 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), AVAHI_PROTO_UNSPEC);
1380 return d->priv->address_family;
1383 static void aui_service_dialog_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
1384 AuiServiceDialog *d = AUI_SERVICE_DIALOG(object);
1387 case PROP_BROWSE_SERVICE_TYPES:
1388 aui_service_dialog_set_browse_service_typesv(d, g_value_get_pointer(value));
1392 aui_service_dialog_set_domain(d, g_value_get_string(value));
1395 case PROP_SERVICE_TYPE:
1396 aui_service_dialog_set_service_type(d, g_value_get_string(value));
1399 case PROP_SERVICE_NAME:
1400 aui_service_dialog_set_service_name(d, g_value_get_string(value));
1403 case PROP_RESOLVE_SERVICE:
1404 aui_service_dialog_set_resolve_service(d, g_value_get_boolean(value));
1407 case PROP_RESOLVE_HOST_NAME:
1408 aui_service_dialog_set_resolve_host_name(d, g_value_get_boolean(value));
1411 case PROP_ADDRESS_FAMILY:
1412 aui_service_dialog_set_address_family(d, g_value_get_int(value));
1416 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1421 static void aui_service_dialog_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
1422 AuiServiceDialog *d = AUI_SERVICE_DIALOG(object);
1425 case PROP_BROWSE_SERVICE_TYPES:
1426 g_value_set_pointer(value, (gpointer) aui_service_dialog_get_browse_service_types(d));
1430 g_value_set_string(value, aui_service_dialog_get_domain(d));
1433 case PROP_SERVICE_TYPE:
1434 g_value_set_string(value, aui_service_dialog_get_service_type(d));
1437 case PROP_SERVICE_NAME:
1438 g_value_set_string(value, aui_service_dialog_get_service_name(d));
1442 g_value_set_pointer(value, (gpointer) aui_service_dialog_get_address(d));
1446 g_value_set_uint(value, aui_service_dialog_get_port(d));
1449 case PROP_HOST_NAME:
1450 g_value_set_string(value, aui_service_dialog_get_host_name(d));
1454 g_value_set_pointer(value, (gpointer) aui_service_dialog_get_txt_data(d));
1457 case PROP_RESOLVE_SERVICE:
1458 g_value_set_boolean(value, aui_service_dialog_get_resolve_service(d));
1461 case PROP_RESOLVE_HOST_NAME:
1462 g_value_set_boolean(value, aui_service_dialog_get_resolve_host_name(d));
1465 case PROP_ADDRESS_FAMILY:
1466 g_value_set_int(value, aui_service_dialog_get_address_family(d));
1470 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);