4 This file is part of avahi.
6 avahi is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 avahi is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14 Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with avahi; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include <sys/types.h>
27 #include <sys/socket.h>
34 #include <avahi-glib/glib-watch.h>
35 #include <avahi-client/client.h>
36 #include <avahi-client/lookup.h>
37 #include <avahi-common/error.h>
38 #include <avahi-common/address.h>
39 #include <avahi-common/domain.h>
43 #if defined(HAVE_GDBM) || defined(HAVE_DBM)
44 #include "../avahi-utils/stdb.h"
47 /* todo: i18n, HIGify */
49 struct _AuiServiceDialogPrivate {
50 AvahiGLibPoll *glib_poll;
52 AvahiServiceBrowser **browsers;
53 AvahiServiceResolver *resolver;
54 AvahiDomainBrowser *domain_browser;
56 gchar **browse_service_types;
60 AvahiProtocol address_family;
64 AvahiStringList *txt_data;
67 gboolean resolve_service, resolve_service_done;
68 gboolean resolve_host_name, resolve_host_name_done;
70 GtkWidget *domain_label;
71 GtkWidget *domain_button;
72 GtkWidget *service_tree_view;
73 GtkWidget *service_progress_bar;
75 GtkListStore *service_list_store, *domain_list_store;
76 GHashTable *service_type_names;
78 guint service_pulse_timeout;
79 guint domain_pulse_timeout;
82 AvahiIfIndex common_interface;
83 AvahiProtocol common_protocol;
85 GtkWidget *domain_dialog;
86 GtkWidget *domain_entry;
87 GtkWidget *domain_tree_view;
88 GtkWidget *domain_progress_bar;
89 GtkWidget *domain_ok_button;
91 gint forward_response_id;
96 PROP_BROWSE_SERVICE_TYPES,
104 PROP_RESOLVE_SERVICE,
105 PROP_RESOLVE_HOST_NAME,
110 SERVICE_COLUMN_IFACE,
111 SERVICE_COLUMN_PROTO,
114 SERVICE_COLUMN_PRETTY_IFACE,
115 SERVICE_COLUMN_PRETTY_TYPE,
125 static void aui_service_dialog_finalize(GObject *object);
126 static void aui_service_dialog_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
127 static void aui_service_dialog_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
129 static int get_default_response(GtkDialog *dlg) {
130 gint ret = GTK_RESPONSE_NONE;
132 if (GTK_WINDOW(dlg)->default_widget)
133 /* Use the response of the default widget, if possible */
134 ret = gtk_dialog_get_response_for_widget(dlg, GTK_WINDOW(dlg)->default_widget);
136 if (ret == GTK_RESPONSE_NONE) {
137 /* Fall back to finding the first positive response */
139 gint bad = GTK_RESPONSE_NONE;
141 t = children = gtk_container_get_children(GTK_CONTAINER(dlg->action_area));
144 GtkWidget *child = t->data;
146 ret = gtk_dialog_get_response_for_widget(dlg, child);
148 if (ret == GTK_RESPONSE_ACCEPT ||
149 ret == GTK_RESPONSE_OK ||
150 ret == GTK_RESPONSE_YES ||
151 ret == GTK_RESPONSE_APPLY)
154 if (ret != GTK_RESPONSE_NONE && bad == GTK_RESPONSE_NONE)
160 g_list_free (children);
162 /* Fall back to finding the first negative response */
163 if (ret == GTK_RESPONSE_NONE)
170 G_DEFINE_TYPE(AuiServiceDialog, aui_service_dialog, GTK_TYPE_DIALOG)
172 static void aui_service_dialog_class_init(AuiServiceDialogClass *klass) {
173 GObjectClass *object_class;
175 object_class = (GObjectClass*) klass;
177 object_class->finalize = aui_service_dialog_finalize;
178 object_class->set_property = aui_service_dialog_set_property;
179 object_class->get_property = aui_service_dialog_get_property;
181 g_object_class_install_property(
183 PROP_BROWSE_SERVICE_TYPES,
184 g_param_spec_pointer("browse_service_types", "Browse Service Types", "A NULL terminated list of service types to browse for",
185 G_PARAM_READABLE | G_PARAM_WRITABLE));
186 g_object_class_install_property(
189 g_param_spec_string("domain", "Domain", "The domain to browse in, or NULL for the default domain",
191 G_PARAM_READABLE | G_PARAM_WRITABLE));
192 g_object_class_install_property(
195 g_param_spec_string("service_type", "Service Type", "The service type of the selected service",
197 G_PARAM_READABLE | G_PARAM_WRITABLE));
198 g_object_class_install_property(
201 g_param_spec_string("service_name", "Service Name", "The service name of the selected service",
203 G_PARAM_READABLE | G_PARAM_WRITABLE));
204 g_object_class_install_property(
207 g_param_spec_pointer("address", "Address", "The address of the resolved service",
209 g_object_class_install_property(
212 g_param_spec_uint("port", "Port", "The IP port number of the resolved service",
215 g_object_class_install_property(
218 g_param_spec_string("host_name", "Host Name", "The host name of the resolved service",
221 g_object_class_install_property(
224 g_param_spec_pointer("txt_data", "TXT Data", "The TXT data of the resolved service",
226 g_object_class_install_property(
228 PROP_RESOLVE_SERVICE,
229 g_param_spec_boolean("resolve_service", "Resolve service", "Resolve service",
231 G_PARAM_READABLE | G_PARAM_WRITABLE));
232 g_object_class_install_property(
234 PROP_RESOLVE_HOST_NAME,
235 g_param_spec_boolean("resolve_host_name", "Resolve service host name", "Resolve service host name",
237 G_PARAM_READABLE | G_PARAM_WRITABLE));
238 g_object_class_install_property(
241 g_param_spec_int("address_family", "Address family", "The address family for host name resolution",
242 AVAHI_PROTO_UNSPEC, AVAHI_PROTO_INET6, AVAHI_PROTO_UNSPEC,
243 G_PARAM_READABLE | G_PARAM_WRITABLE));
247 GtkWidget *aui_service_dialog_new_valist(
250 const gchar *first_button_text,
253 const gchar *button_text;
256 GtkWidget *w = GTK_WIDGET(g_object_new(
257 AUI_TYPE_SERVICE_DIALOG,
258 "has-separator", FALSE,
263 gtk_window_set_transient_for(GTK_WINDOW(w), parent);
265 button_text = first_button_text;
266 while (button_text) {
269 response_id = va_arg(varargs, gint);
270 gtk_dialog_add_button(GTK_DIALOG(w), button_text, response_id);
271 button_text = va_arg(varargs, const gchar *);
274 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_ACCEPT, FALSE);
275 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_OK, FALSE);
276 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_YES, FALSE);
277 gtk_dialog_set_response_sensitive(GTK_DIALOG(w), GTK_RESPONSE_APPLY, FALSE);
279 if ((dr = get_default_response(GTK_DIALOG(w))) != GTK_RESPONSE_NONE)
280 gtk_dialog_set_default_response(GTK_DIALOG(w), dr);
285 GtkWidget* aui_service_dialog_new(
288 const gchar *first_button_text,
294 va_start(varargs, first_button_text);
295 w = aui_service_dialog_new_valist(title, parent, first_button_text, varargs);
301 static gboolean service_pulse_callback(gpointer data) {
302 AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
304 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->priv->service_progress_bar));
308 static gboolean domain_pulse_callback(gpointer data) {
309 AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
311 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(d->priv->domain_progress_bar));
315 static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
316 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
318 if (state == AVAHI_CLIENT_FAILURE) {
319 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
320 GTK_DIALOG_DESTROY_WITH_PARENT,
323 "Avahi client failure: %s",
324 avahi_strerror(avahi_client_errno(c)));
325 gtk_dialog_run(GTK_DIALOG(m));
326 gtk_widget_destroy(m);
328 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
332 static void resolve_callback(
333 AvahiServiceResolver *r G_GNUC_UNUSED,
334 AvahiIfIndex interface G_GNUC_UNUSED,
335 AvahiProtocol protocol G_GNUC_UNUSED,
336 AvahiResolverEvent event,
340 const char *host_name,
341 const AvahiAddress *a,
343 AvahiStringList *txt,
344 AvahiLookupResultFlags flags G_GNUC_UNUSED,
347 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
350 case AVAHI_RESOLVER_FOUND:
352 d->priv->resolve_service_done = 1;
354 g_free(d->priv->service_name);
355 d->priv->service_name = g_strdup(name);
357 g_free(d->priv->service_type);
358 d->priv->service_type = g_strdup(type);
360 g_free(d->priv->domain);
361 d->priv->domain = g_strdup(domain);
363 g_free(d->priv->host_name);
364 d->priv->host_name = g_strdup(host_name);
366 d->priv->port = port;
368 avahi_string_list_free(d->priv->txt_data);
369 d->priv->txt_data = avahi_string_list_copy(txt);
372 d->priv->resolve_host_name_done = 1;
373 d->priv->address = *a;
376 gtk_dialog_response(GTK_DIALOG(d), d->priv->forward_response_id);
380 case AVAHI_RESOLVER_FAILURE: {
381 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
382 GTK_DIALOG_DESTROY_WITH_PARENT,
385 "Avahi resolver failure: %s",
386 avahi_strerror(avahi_client_errno(d->priv->client)));
387 gtk_dialog_run(GTK_DIALOG(m));
388 gtk_widget_destroy(m);
390 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
397 static void browse_callback(
398 AvahiServiceBrowser *b G_GNUC_UNUSED,
399 AvahiIfIndex interface,
400 AvahiProtocol protocol,
401 AvahiBrowserEvent event,
405 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
408 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
412 case AVAHI_BROWSER_NEW: {
414 const gchar *pretty_type = NULL;
415 char ifname[IFNAMSIZ];
417 GtkTreeSelection *selection;
419 if (!(if_indextoname(interface, ifname)))
420 g_snprintf(ifname, sizeof(ifname), "%i", interface);
422 ifs = g_strdup_printf("%s %s", ifname, protocol == AVAHI_PROTO_INET ? "IPv4" : "IPv6");
424 if (d->priv->service_type_names)
425 pretty_type = g_hash_table_lookup (d->priv->service_type_names, type);
428 #if defined(HAVE_GDBM) || defined(HAVE_DBM)
429 pretty_type = stdb_lookup(type);
435 gtk_list_store_append(d->priv->service_list_store, &iter);
437 gtk_list_store_set(d->priv->service_list_store, &iter,
438 SERVICE_COLUMN_IFACE, interface,
439 SERVICE_COLUMN_PROTO, protocol,
440 SERVICE_COLUMN_NAME, name,
441 SERVICE_COLUMN_TYPE, type,
442 SERVICE_COLUMN_PRETTY_IFACE, ifs,
443 SERVICE_COLUMN_PRETTY_TYPE, pretty_type,
448 if (d->priv->common_protocol == AVAHI_PROTO_UNSPEC)
449 d->priv->common_protocol = protocol;
451 if (d->priv->common_interface == AVAHI_IF_UNSPEC)
452 d->priv->common_interface = interface;
454 if (d->priv->common_interface != interface || d->priv->common_protocol != protocol) {
455 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 0), TRUE);
456 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), TRUE);
459 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->service_tree_view));
460 if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) {
462 if (!d->priv->service_type ||
463 !d->priv->service_name ||
464 (avahi_domain_equal(d->priv->service_type, type) && strcasecmp(d->priv->service_name, name) == 0)) {
467 gtk_tree_selection_select_iter(selection, &iter);
469 path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
470 gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->priv->service_tree_view), path, NULL, FALSE);
471 gtk_tree_path_free(path);
479 case AVAHI_BROWSER_REMOVE: {
483 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
485 gint _interface, _protocol;
486 gchar *_name, *_type;
489 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->service_list_store), &iter,
490 SERVICE_COLUMN_IFACE, &_interface,
491 SERVICE_COLUMN_PROTO, &_protocol,
492 SERVICE_COLUMN_NAME, &_name,
493 SERVICE_COLUMN_TYPE, &_type,
496 found = _interface == interface && _protocol == protocol && strcasecmp(_name, name) == 0 && avahi_domain_equal(_type, type);
500 gtk_list_store_remove(d->priv->service_list_store, &iter);
504 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->service_list_store), &iter);
510 case AVAHI_BROWSER_FAILURE: {
511 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
512 GTK_DIALOG_DESTROY_WITH_PARENT,
515 "Browsing for service type %s in domain %s failed: %s",
516 type, domain ? domain : "n/a",
517 avahi_strerror(avahi_client_errno(d->priv->client)));
518 gtk_dialog_run(GTK_DIALOG(m));
519 gtk_widget_destroy(m);
524 case AVAHI_BROWSER_ALL_FOR_NOW:
525 if (d->priv->service_pulse_timeout > 0) {
526 g_source_remove(d->priv->service_pulse_timeout);
527 d->priv->service_pulse_timeout = 0;
528 gtk_widget_hide(d->priv->service_progress_bar);
532 case AVAHI_BROWSER_CACHE_EXHAUSTED:
537 static void domain_make_default_selection(AuiServiceDialog *d, const gchar *name, GtkTreeIter *iter) {
538 GtkTreeSelection *selection;
540 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->domain_tree_view));
541 if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) {
543 if (avahi_domain_equal(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry)), name)) {
546 gtk_tree_selection_select_iter(selection, iter);
548 path = gtk_tree_model_get_path(GTK_TREE_MODEL(d->priv->domain_list_store), iter);
549 gtk_tree_view_set_cursor(GTK_TREE_VIEW(d->priv->domain_tree_view), path, NULL, FALSE);
550 gtk_tree_path_free(path);
556 static void domain_browse_callback(
557 AvahiDomainBrowser *b G_GNUC_UNUSED,
558 AvahiIfIndex interface G_GNUC_UNUSED,
559 AvahiProtocol protocol G_GNUC_UNUSED,
560 AvahiBrowserEvent event,
562 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
565 AuiServiceDialog *d = AUI_SERVICE_DIALOG(userdata);
569 case AVAHI_BROWSER_NEW: {
571 gboolean found = FALSE, valid;
574 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
578 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
579 DOMAIN_COLUMN_NAME, &_name,
580 DOMAIN_COLUMN_REF, &ref,
583 found = avahi_domain_equal(_name, name);
589 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
593 gtk_list_store_set(d->priv->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref + 1, -1);
595 gtk_list_store_append(d->priv->domain_list_store, &iter);
597 gtk_list_store_set(d->priv->domain_list_store, &iter,
598 DOMAIN_COLUMN_NAME, name,
599 DOMAIN_COLUMN_REF, 1,
603 domain_make_default_selection(d, name, &iter);
608 case AVAHI_BROWSER_REMOVE: {
612 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
618 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
619 DOMAIN_COLUMN_NAME, &_name,
620 DOMAIN_COLUMN_REF, &ref,
623 found = avahi_domain_equal(_name, name);
628 gtk_list_store_remove(d->priv->service_list_store, &iter);
630 gtk_list_store_set(d->priv->domain_list_store, &iter, DOMAIN_COLUMN_REF, ref - 1, -1);
634 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(d->priv->domain_list_store), &iter);
641 case AVAHI_BROWSER_FAILURE: {
642 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
643 GTK_DIALOG_DESTROY_WITH_PARENT,
646 "Avahi domain browser failure: %s",
647 avahi_strerror(avahi_client_errno(d->priv->client)));
648 gtk_dialog_run(GTK_DIALOG(m));
649 gtk_widget_destroy(m);
654 case AVAHI_BROWSER_ALL_FOR_NOW:
655 if (d->priv->domain_pulse_timeout > 0) {
656 g_source_remove(d->priv->domain_pulse_timeout);
657 d->priv->domain_pulse_timeout = 0;
658 gtk_widget_hide(d->priv->domain_progress_bar);
662 case AVAHI_BROWSER_CACHE_EXHAUSTED:
667 static const gchar *get_domain_name(AuiServiceDialog *d) {
670 g_return_val_if_fail(d, NULL);
671 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
674 return d->priv->domain;
676 if (!(domain = avahi_client_get_domain_name(d->priv->client))) {
677 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
678 GTK_DIALOG_DESTROY_WITH_PARENT,
681 "Failed to read Avahi domain : %s",
682 avahi_strerror(avahi_client_errno(d->priv->client)));
683 gtk_dialog_run(GTK_DIALOG(m));
684 gtk_widget_destroy(m);
692 static gboolean start_callback(gpointer data) {
694 AuiServiceDialog *d = AUI_SERVICE_DIALOG(data);
696 AvahiServiceBrowser **sb;
700 d->priv->start_idle = 0;
702 if (!d->priv->browse_service_types || !*d->priv->browse_service_types) {
703 g_warning("Browse service type list is empty!");
707 if (!d->priv->client) {
708 if (!(d->priv->client = avahi_client_new(avahi_glib_poll_get(d->priv->glib_poll), 0, client_callback, d, &error))) {
710 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
711 GTK_DIALOG_DESTROY_WITH_PARENT,
714 "Failed to connect to Avahi server: %s",
715 avahi_strerror(error));
716 gtk_dialog_run(GTK_DIALOG(m));
717 gtk_widget_destroy(m);
719 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
724 if (!(domain = get_domain_name(d))) {
725 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
731 if (avahi_domain_equal(domain, "local."))
732 gtk_label_set_markup(GTK_LABEL(d->priv->domain_label), "Browsing for services on <b>local network</b>:");
734 gchar *t = g_strdup_printf("Browsing for services in domain <b>%s</b>:", domain);
735 gtk_label_set_markup(GTK_LABEL(d->priv->domain_label), t);
739 if (d->priv->browsers) {
740 for (sb = d->priv->browsers; *sb; sb++)
741 avahi_service_browser_free(*sb);
743 g_free(d->priv->browsers);
744 d->priv->browsers = NULL;
747 gtk_list_store_clear(GTK_LIST_STORE(d->priv->service_list_store));
748 d->priv->common_interface = AVAHI_IF_UNSPEC;
749 d->priv->common_protocol = AVAHI_PROTO_UNSPEC;
751 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 0), FALSE);
752 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d->priv->service_tree_view), FALSE);
753 gtk_widget_show(d->priv->service_progress_bar);
755 if (d->priv->service_pulse_timeout <= 0)
756 d->priv->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
758 for (i = 0; d->priv->browse_service_types[i]; i++)
762 d->priv->browsers = g_new0(AvahiServiceBrowser*, i+1);
763 for (st = d->priv->browse_service_types, sb = d->priv->browsers; *st; st++, sb++) {
765 if (!(*sb = avahi_service_browser_new(d->priv->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, *st, d->priv->domain, 0, browse_callback, d))) {
766 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
767 GTK_DIALOG_DESTROY_WITH_PARENT,
770 "Failed to create browser for %s: %s",
772 avahi_strerror(avahi_client_errno(d->priv->client)));
773 gtk_dialog_run(GTK_DIALOG(m));
774 gtk_widget_destroy(m);
776 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
785 static void aui_service_dialog_finalize(GObject *object) {
786 AuiServiceDialog *d = AUI_SERVICE_DIALOG(object);
788 if (d->priv->domain_pulse_timeout > 0)
789 g_source_remove(d->priv->domain_pulse_timeout);
791 if (d->priv->service_pulse_timeout > 0)
792 g_source_remove(d->priv->service_pulse_timeout);
794 if (d->priv->start_idle > 0)
795 g_source_remove(d->priv->start_idle);
797 g_free(d->priv->host_name);
798 g_free(d->priv->domain);
799 g_free(d->priv->service_name);
801 avahi_string_list_free(d->priv->txt_data);
803 g_strfreev(d->priv->browse_service_types);
805 if (d->priv->domain_browser)
806 avahi_domain_browser_free(d->priv->domain_browser);
808 if (d->priv->resolver)
809 avahi_service_resolver_free(d->priv->resolver);
811 if (d->priv->browsers) {
812 AvahiServiceBrowser **sb;
814 for (sb = d->priv->browsers; *sb; sb++)
815 avahi_service_browser_free(*sb);
817 g_free(d->priv->browsers);
821 avahi_client_free(d->priv->client);
823 if (d->priv->glib_poll)
824 avahi_glib_poll_free(d->priv->glib_poll);
826 if (d->priv->service_list_store)
827 g_object_unref(d->priv->service_list_store);
828 if (d->priv->domain_list_store)
829 g_object_unref(d->priv->domain_list_store);
830 if (d->priv->service_type_names)
831 g_hash_table_unref (d->priv->service_type_names);
836 G_OBJECT_CLASS(aui_service_dialog_parent_class)->finalize(object);
839 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) {
840 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
842 gtk_dialog_response(GTK_DIALOG(d), get_default_response(GTK_DIALOG(d)));
845 static void service_selection_changed_callback(GtkTreeSelection *selection, gpointer user_data) {
846 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
849 b = gtk_tree_selection_get_selected(selection, NULL, NULL);
850 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT, b);
851 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_OK, b);
852 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_YES, b);
853 gtk_dialog_set_response_sensitive(GTK_DIALOG(d), GTK_RESPONSE_APPLY, b);
856 static void response_callback(GtkDialog *dialog, gint response, gpointer user_data) {
857 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
859 if ((response == GTK_RESPONSE_ACCEPT ||
860 response == GTK_RESPONSE_OK ||
861 response == GTK_RESPONSE_YES ||
862 response == GTK_RESPONSE_APPLY) &&
863 ((d->priv->resolve_service && !d->priv->resolve_service_done) ||
864 (d->priv->resolve_host_name && !d->priv->resolve_host_name_done))) {
867 gint interface, protocol;
871 g_signal_stop_emission(dialog, g_signal_lookup("response", gtk_dialog_get_type()), 0);
872 d->priv->forward_response_id = response;
874 if (d->priv->resolver)
877 g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->service_tree_view)), NULL, &iter));
879 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->service_list_store), &iter,
880 SERVICE_COLUMN_IFACE, &interface,
881 SERVICE_COLUMN_PROTO, &protocol,
882 SERVICE_COLUMN_NAME, &name,
883 SERVICE_COLUMN_TYPE, &type, -1);
885 g_return_if_fail(d->priv->client);
887 gtk_widget_set_sensitive(GTK_WIDGET(dialog), FALSE);
888 cursor = gdk_cursor_new(GDK_WATCH);
889 gdk_window_set_cursor(GTK_WIDGET(dialog)->window, cursor);
890 gdk_cursor_unref(cursor);
892 if (!(d->priv->resolver = avahi_service_resolver_new(
893 d->priv->client, interface, protocol, name, type, d->priv->domain,
894 d->priv->address_family, !d->priv->resolve_host_name ? AVAHI_LOOKUP_NO_ADDRESS : 0, resolve_callback, d))) {
896 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
897 GTK_DIALOG_DESTROY_WITH_PARENT,
900 "Failed to create resolver for %s of type %s in domain %s: %s",
901 name, type, d->priv->domain,
902 avahi_strerror(avahi_client_errno(d->priv->client)));
903 gtk_dialog_run(GTK_DIALOG(m));
904 gtk_widget_destroy(m);
906 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
912 static gboolean is_valid_domain_suffix(const gchar *n) {
913 gchar label[AVAHI_LABEL_MAX];
915 if (!avahi_is_valid_domain_name(n))
918 if (!avahi_unescape_label(&n, label, sizeof(label)))
921 /* At least one label */
926 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) {
927 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
929 if (is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry))))
930 gtk_dialog_response(GTK_DIALOG(d->priv->domain_dialog), GTK_RESPONSE_ACCEPT);
933 static void domain_selection_changed_callback(GtkTreeSelection *selection G_GNUC_UNUSED, gpointer user_data) {
935 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
938 g_return_if_fail(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(d->priv->domain_tree_view)), NULL, &iter));
940 gtk_tree_model_get(GTK_TREE_MODEL(d->priv->domain_list_store), &iter,
941 DOMAIN_COLUMN_NAME, &name, -1);
943 gtk_entry_set_text(GTK_ENTRY(d->priv->domain_entry), name);
946 static void domain_entry_changed_callback(GtkEditable *editable G_GNUC_UNUSED, gpointer user_data) {
947 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
949 gtk_widget_set_sensitive(d->priv->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(d->priv->domain_entry))));
952 static void domain_button_clicked(GtkButton *button G_GNUC_UNUSED, gpointer user_data) {
953 GtkWidget *vbox, *vbox2, *scrolled_window;
954 GtkTreeSelection *selection;
955 GtkCellRenderer *renderer;
956 GtkTreeViewColumn *column;
957 AuiServiceDialog *d = AUI_SERVICE_DIALOG(user_data);
958 AuiServiceDialogPrivate *p = d->priv;
962 g_return_if_fail(!p->domain_dialog);
963 g_return_if_fail(!p->domain_browser);
965 if (!(domain = get_domain_name(d))) {
966 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
970 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))) {
971 GtkWidget *m = gtk_message_dialog_new(GTK_WINDOW(d),
972 GTK_DIALOG_DESTROY_WITH_PARENT,
975 "Failed to create domain browser: %s",
976 avahi_strerror(avahi_client_errno(p->client)));
977 gtk_dialog_run(GTK_DIALOG(m));
978 gtk_widget_destroy(m);
980 gtk_dialog_response(GTK_DIALOG(d), GTK_RESPONSE_CANCEL);
984 p->domain_dialog = gtk_dialog_new();
985 gtk_container_set_border_width(GTK_CONTAINER(p->domain_dialog), 5);
986 gtk_window_set_title(GTK_WINDOW(p->domain_dialog), "Change domain");
987 gtk_dialog_set_has_separator(GTK_DIALOG(p->domain_dialog), FALSE);
989 vbox = gtk_vbox_new(FALSE, 8);
990 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
991 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(p->domain_dialog)->vbox), vbox, TRUE, TRUE, 0);
993 p->domain_entry = gtk_entry_new();
994 gtk_entry_set_max_length(GTK_ENTRY(p->domain_entry), AVAHI_DOMAIN_NAME_MAX);
995 gtk_entry_set_text(GTK_ENTRY(p->domain_entry), domain);
996 gtk_entry_set_activates_default(GTK_ENTRY(p->domain_entry), TRUE);
997 g_signal_connect(p->domain_entry, "changed", G_CALLBACK(domain_entry_changed_callback), d);
998 gtk_box_pack_start(GTK_BOX(vbox), p->domain_entry, FALSE, FALSE, 0);
1000 vbox2 = gtk_vbox_new(FALSE, 8);
1001 gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
1003 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1004 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1005 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
1006 gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0);
1008 p->domain_list_store = gtk_list_store_new(N_DOMAIN_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
1010 p->domain_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p->domain_list_store));
1011 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(p->domain_tree_view), FALSE);
1012 g_signal_connect(p->domain_tree_view, "row-activated", G_CALLBACK(domain_row_activated_callback), d);
1013 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(p->domain_tree_view));
1014 gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
1015 g_signal_connect(selection, "changed", G_CALLBACK(domain_selection_changed_callback), d);
1017 renderer = gtk_cell_renderer_text_new();
1018 column = gtk_tree_view_column_new_with_attributes("Service Name", renderer, "text", DOMAIN_COLUMN_NAME, NULL);
1019 gtk_tree_view_column_set_expand(column, TRUE);
1020 gtk_tree_view_append_column(GTK_TREE_VIEW(p->domain_tree_view), column);
1022 gtk_tree_view_set_search_column(GTK_TREE_VIEW(p->domain_tree_view), DOMAIN_COLUMN_NAME);
1023 gtk_container_add(GTK_CONTAINER(scrolled_window), p->domain_tree_view);
1025 p->domain_progress_bar = gtk_progress_bar_new();
1026 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(p->domain_progress_bar), "Browsing ...");
1027 gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(p->domain_progress_bar), 0.1);
1028 gtk_box_pack_end(GTK_BOX(vbox2), p->domain_progress_bar, FALSE, FALSE, 0);
1030 gtk_dialog_add_button(GTK_DIALOG(p->domain_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1031 p->domain_ok_button = GTK_WIDGET(gtk_dialog_add_button(GTK_DIALOG(p->domain_dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT));
1032 gtk_dialog_set_default_response(GTK_DIALOG(p->domain_dialog), GTK_RESPONSE_ACCEPT);
1033 gtk_widget_set_sensitive(p->domain_ok_button, is_valid_domain_suffix(gtk_entry_get_text(GTK_ENTRY(p->domain_entry))));
1035 gtk_widget_grab_default(p->domain_ok_button);
1036 gtk_widget_grab_focus(p->domain_entry);
1038 gtk_window_set_default_size(GTK_WINDOW(p->domain_dialog), 300, 300);
1040 gtk_widget_show_all(vbox);
1042 gtk_list_store_append(p->domain_list_store, &iter);
1043 gtk_list_store_set(p->domain_list_store, &iter, DOMAIN_COLUMN_NAME, "local", DOMAIN_COLUMN_REF, 1, -1);
1044 domain_make_default_selection(d, "local", &iter);
1046 p->domain_pulse_timeout = g_timeout_add(100, domain_pulse_callback, d);
1048 if (gtk_dialog_run(GTK_DIALOG(p->domain_dialog)) == GTK_RESPONSE_ACCEPT)
1049 aui_service_dialog_set_domain(d, gtk_entry_get_text(GTK_ENTRY(p->domain_entry)));
1051 gtk_widget_destroy(p->domain_dialog);
1052 p->domain_dialog = NULL;
1054 if (p->domain_pulse_timeout > 0) {
1055 g_source_remove(p->domain_pulse_timeout);
1056 p->domain_pulse_timeout = 0;
1059 avahi_domain_browser_free(p->domain_browser);
1060 p->domain_browser = NULL;
1063 static void aui_service_dialog_init(AuiServiceDialog *d) {
1064 GtkWidget *vbox, *vbox2, *scrolled_window;
1065 GtkCellRenderer *renderer;
1066 GtkTreeViewColumn *column;
1067 GtkTreeSelection *selection;
1068 AuiServiceDialogPrivate *p;
1070 p = d->priv = g_new(AuiServiceDialogPrivate, 1);
1072 p->host_name = NULL;
1074 p->service_name = NULL;
1075 p->service_type = NULL;
1077 p->browse_service_types = NULL;
1078 memset(&p->address, 0, sizeof(p->address));
1080 p->resolve_host_name = p->resolve_service = TRUE;
1081 p->resolve_host_name_done = p->resolve_service_done = FALSE;
1082 p->address_family = AVAHI_PROTO_UNSPEC;
1084 p->glib_poll = NULL;
1088 p->domain_browser = NULL;
1090 p->service_pulse_timeout = 0;
1091 p->domain_pulse_timeout = 0;
1093 p->common_interface = AVAHI_IF_UNSPEC;
1094 p->common_protocol = AVAHI_PROTO_UNSPEC;
1096 p->domain_dialog = NULL;
1097 p->domain_entry = NULL;
1098 p->domain_tree_view = NULL;
1099 p->domain_progress_bar = NULL;
1100 p->domain_ok_button = NULL;
1102 p->forward_response_id = GTK_RESPONSE_NONE;
1104 p->service_list_store = p->domain_list_store = NULL;
1105 p->service_type_names = NULL;
1107 gtk_widget_push_composite_child();
1109 gtk_container_set_border_width(GTK_CONTAINER(d), 5);
1111 vbox = gtk_vbox_new(FALSE, 8);
1112 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
1113 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d)->vbox), vbox, TRUE, TRUE, 0);
1115 p->domain_label = gtk_label_new("Initializing...");
1116 gtk_label_set_ellipsize(GTK_LABEL(p->domain_label), TRUE);
1117 gtk_misc_set_alignment(GTK_MISC(p->domain_label), 0, 0.5);
1118 gtk_box_pack_start(GTK_BOX(vbox), p->domain_label, FALSE, FALSE, 0);
1121 vbox2 = gtk_vbox_new(FALSE, 8);
1122 gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
1124 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1125 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1126 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
1127 gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0);
1129 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);
1131 p->service_tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p->service_list_store));
1132 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(p->service_tree_view), FALSE);
1133 g_signal_connect(p->service_tree_view, "row-activated", G_CALLBACK(service_row_activated_callback), d);
1134 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(p->service_tree_view));
1135 gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
1136 g_signal_connect(selection, "changed", G_CALLBACK(service_selection_changed_callback), d);
1138 renderer = gtk_cell_renderer_text_new();
1139 column = gtk_tree_view_column_new_with_attributes("Location", renderer, "text", SERVICE_COLUMN_PRETTY_IFACE, NULL);
1140 gtk_tree_view_column_set_visible(column, FALSE);
1141 gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
1143 renderer = gtk_cell_renderer_text_new();
1144 column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", SERVICE_COLUMN_NAME, NULL);
1145 gtk_tree_view_column_set_expand(column, TRUE);
1146 gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
1148 renderer = gtk_cell_renderer_text_new();
1149 column = gtk_tree_view_column_new_with_attributes("Type", renderer, "text", SERVICE_COLUMN_PRETTY_TYPE, NULL);
1150 gtk_tree_view_column_set_visible(column, FALSE);
1151 gtk_tree_view_append_column(GTK_TREE_VIEW(p->service_tree_view), column);
1153 gtk_tree_view_set_search_column(GTK_TREE_VIEW(p->service_tree_view), SERVICE_COLUMN_NAME);
1154 gtk_container_add(GTK_CONTAINER(scrolled_window), p->service_tree_view);
1156 p->service_progress_bar = gtk_progress_bar_new();
1157 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(p->service_progress_bar), "Browsing ...");
1158 gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(p->service_progress_bar), 0.1);
1159 gtk_box_pack_end(GTK_BOX(vbox2), p->service_progress_bar, FALSE, FALSE, 0);
1161 p->domain_button = gtk_button_new_with_mnemonic("_Domain...");
1162 gtk_button_set_image(GTK_BUTTON(p->domain_button), gtk_image_new_from_stock(GTK_STOCK_NETWORK, GTK_ICON_SIZE_BUTTON));
1163 g_signal_connect(p->domain_button, "clicked", G_CALLBACK(domain_button_clicked), d);
1164 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d)->action_area), p->domain_button, FALSE, TRUE, 0);
1165 gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(GTK_DIALOG(d)->action_area), p->domain_button, TRUE);
1166 gtk_widget_show(p->domain_button);
1168 gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT);
1170 gtk_widget_grab_focus(p->service_tree_view);
1172 gtk_window_set_default_size(GTK_WINDOW(d), 400, 300);
1174 gtk_widget_show_all(vbox);
1176 gtk_widget_pop_composite_child();
1178 p->glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
1180 p->service_pulse_timeout = g_timeout_add(100, service_pulse_callback, d);
1181 p->start_idle = g_idle_add(start_callback, d);
1183 g_signal_connect(d, "response", G_CALLBACK(response_callback), d);
1186 static void restart_browsing(AuiServiceDialog *d) {
1187 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1189 if (d->priv->start_idle <= 0)
1190 d->priv->start_idle = g_idle_add(start_callback, d);
1193 void aui_service_dialog_set_browse_service_types(AuiServiceDialog *d, const char *type, ...) {
1198 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1199 g_return_if_fail(type);
1201 g_strfreev(d->priv->browse_service_types);
1204 for (u = 1; va_arg(ap, const char *); u++)
1208 d->priv->browse_service_types = g_new0(gchar*, u+1);
1209 d->priv->browse_service_types[0] = g_strdup(type);
1212 for (u = 1; (t = va_arg(ap, const char*)); u++)
1213 d->priv->browse_service_types[u] = g_strdup(t);
1216 if (d->priv->browse_service_types[0] && d->priv->browse_service_types[1]) {
1217 /* Multiple service types, show type-column */
1218 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 2), TRUE);
1221 restart_browsing(d);
1224 void aui_service_dialog_set_browse_service_typesv(AuiServiceDialog *d, const char *const*types) {
1226 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1227 g_return_if_fail(types);
1228 g_return_if_fail(*types);
1230 g_strfreev(d->priv->browse_service_types);
1231 d->priv->browse_service_types = g_strdupv((char**) types);
1233 if (d->priv->browse_service_types[0] && d->priv->browse_service_types[1]) {
1234 /* Multiple service types, show type-column */
1235 gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(d->priv->service_tree_view), 2), TRUE);
1238 restart_browsing(d);
1241 const gchar*const* aui_service_dialog_get_browse_service_types(AuiServiceDialog *d) {
1242 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1244 return (const char* const*) d->priv->browse_service_types;
1247 void aui_service_dialog_set_service_type_name(AuiServiceDialog *d, const gchar *type, const gchar *name) {
1248 GtkTreeModel *m = NULL;
1251 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1252 g_return_if_fail(NULL != type);
1253 g_return_if_fail(NULL != name);
1255 if (NULL == d->priv->service_type_names)
1256 d->priv->service_type_names = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1258 g_hash_table_insert(d->priv->service_type_names, g_strdup(type), g_strdup(name));
1260 if (d->priv->service_list_store)
1261 m = GTK_TREE_MODEL(d->priv->service_list_store);
1263 if (m && gtk_tree_model_get_iter_first(m, &iter)) {
1265 char *stored_type = NULL;
1267 gtk_tree_model_get(m, &iter, SERVICE_COLUMN_TYPE, &stored_type, -1);
1269 if (stored_type && g_str_equal(stored_type, type))
1270 gtk_list_store_set(d->priv->service_list_store, &iter, SERVICE_COLUMN_PRETTY_TYPE, name, -1);
1271 } while (gtk_tree_model_iter_next(m, &iter));
1275 void aui_service_dialog_set_domain(AuiServiceDialog *d, const char *domain) {
1276 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1277 g_return_if_fail(!domain || is_valid_domain_suffix(domain));
1279 g_free(d->priv->domain);
1280 d->priv->domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
1282 restart_browsing(d);
1285 const char* aui_service_dialog_get_domain(AuiServiceDialog *d) {
1286 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1288 return d->priv->domain;
1291 void aui_service_dialog_set_service_name(AuiServiceDialog *d, const char *name) {
1292 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1294 g_free(d->priv->service_name);
1295 d->priv->service_name = g_strdup(name);
1298 const char* aui_service_dialog_get_service_name(AuiServiceDialog *d) {
1299 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1301 return d->priv->service_name;
1304 void aui_service_dialog_set_service_type(AuiServiceDialog *d, const char*stype) {
1305 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1307 g_free(d->priv->service_type);
1308 d->priv->service_type = g_strdup(stype);
1311 const char* aui_service_dialog_get_service_type(AuiServiceDialog *d) {
1312 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1314 return d->priv->service_type;
1317 const AvahiAddress* aui_service_dialog_get_address(AuiServiceDialog *d) {
1318 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1319 g_return_val_if_fail(d->priv->resolve_service_done && d->priv->resolve_host_name_done, NULL);
1321 return &d->priv->address;
1324 guint16 aui_service_dialog_get_port(AuiServiceDialog *d) {
1325 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), 0);
1326 g_return_val_if_fail(d->priv->resolve_service_done, 0);
1328 return d->priv->port;
1331 const char* aui_service_dialog_get_host_name(AuiServiceDialog *d) {
1332 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1333 g_return_val_if_fail(d->priv->resolve_service_done, NULL);
1335 return d->priv->host_name;
1338 const AvahiStringList *aui_service_dialog_get_txt_data(AuiServiceDialog *d) {
1339 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), NULL);
1340 g_return_val_if_fail(d->priv->resolve_service_done, NULL);
1342 return d->priv->txt_data;
1345 void aui_service_dialog_set_resolve_service(AuiServiceDialog *d, gboolean resolve) {
1346 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1348 d->priv->resolve_service = resolve;
1351 gboolean aui_service_dialog_get_resolve_service(AuiServiceDialog *d) {
1352 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), FALSE);
1354 return d->priv->resolve_service;
1357 void aui_service_dialog_set_resolve_host_name(AuiServiceDialog *d, gboolean resolve) {
1358 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1360 d->priv->resolve_host_name = resolve;
1363 gboolean aui_service_dialog_get_resolve_host_name(AuiServiceDialog *d) {
1364 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), FALSE);
1366 return d->priv->resolve_host_name;
1369 void aui_service_dialog_set_address_family(AuiServiceDialog *d, AvahiProtocol proto) {
1370 g_return_if_fail(AUI_IS_SERVICE_DIALOG(d));
1371 g_return_if_fail(proto == AVAHI_PROTO_UNSPEC || proto == AVAHI_PROTO_INET || proto == AVAHI_PROTO_INET6);
1373 d->priv->address_family = proto;
1376 AvahiProtocol aui_service_dialog_get_address_family(AuiServiceDialog *d) {
1377 g_return_val_if_fail(AUI_IS_SERVICE_DIALOG(d), AVAHI_PROTO_UNSPEC);
1379 return d->priv->address_family;
1382 static void aui_service_dialog_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
1383 AuiServiceDialog *d = AUI_SERVICE_DIALOG(object);
1386 case PROP_BROWSE_SERVICE_TYPES:
1387 aui_service_dialog_set_browse_service_typesv(d, g_value_get_pointer(value));
1391 aui_service_dialog_set_domain(d, g_value_get_string(value));
1394 case PROP_SERVICE_TYPE:
1395 aui_service_dialog_set_service_type(d, g_value_get_string(value));
1398 case PROP_SERVICE_NAME:
1399 aui_service_dialog_set_service_name(d, g_value_get_string(value));
1402 case PROP_RESOLVE_SERVICE:
1403 aui_service_dialog_set_resolve_service(d, g_value_get_boolean(value));
1406 case PROP_RESOLVE_HOST_NAME:
1407 aui_service_dialog_set_resolve_host_name(d, g_value_get_boolean(value));
1410 case PROP_ADDRESS_FAMILY:
1411 aui_service_dialog_set_address_family(d, g_value_get_int(value));
1415 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1420 static void aui_service_dialog_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
1421 AuiServiceDialog *d = AUI_SERVICE_DIALOG(object);
1424 case PROP_BROWSE_SERVICE_TYPES:
1425 g_value_set_pointer(value, (gpointer) aui_service_dialog_get_browse_service_types(d));
1429 g_value_set_string(value, aui_service_dialog_get_domain(d));
1432 case PROP_SERVICE_TYPE:
1433 g_value_set_string(value, aui_service_dialog_get_service_type(d));
1436 case PROP_SERVICE_NAME:
1437 g_value_set_string(value, aui_service_dialog_get_service_name(d));
1441 g_value_set_pointer(value, (gpointer) aui_service_dialog_get_address(d));
1445 g_value_set_uint(value, aui_service_dialog_get_port(d));
1448 case PROP_HOST_NAME:
1449 g_value_set_string(value, aui_service_dialog_get_host_name(d));
1453 g_value_set_pointer(value, (gpointer) aui_service_dialog_get_txt_data(d));
1456 case PROP_RESOLVE_SERVICE:
1457 g_value_set_boolean(value, aui_service_dialog_get_resolve_service(d));
1460 case PROP_RESOLVE_HOST_NAME:
1461 g_value_set_boolean(value, aui_service_dialog_get_resolve_host_name(d));
1464 case PROP_ADDRESS_FAMILY:
1465 g_value_set_int(value, aui_service_dialog_get_address_family(d));
1469 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);