aboutsummaryrefslogtreecommitdiffstats
path: root/mdns.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2006-01-26 16:27:01 +0000
committerkraxel <kraxel>2006-01-26 16:27:01 +0000
commit8cefbcf1e028004efa70f2f1956fbc9d25c8b372 (patch)
tree03331d899793e543d06e6e3239bf67981ccae1a1 /mdns.c
parent2bc71f882724947307fadcf5f3c7cee81191acb2 (diff)
downloadxenwatch-8cefbcf1e028004efa70f2f1956fbc9d25c8b372.tar.gz
- more mdns bits.
Diffstat (limited to 'mdns.c')
-rw-r--r--mdns.c655
1 files changed, 582 insertions, 73 deletions
diff --git a/mdns.c b/mdns.c
index 9e27006..ec7d29f 100644
--- a/mdns.c
+++ b/mdns.c
@@ -3,8 +3,15 @@
#include <unistd.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/if.h> /* FIXME: find more portable one */
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
#ifdef HAVE_AVAHI
-# include <glib.h>
# include <avahi-client/client.h>
# include <avahi-client/lookup.h>
# include <avahi-common/error.h>
@@ -18,6 +25,41 @@
#ifdef HAVE_AVAHI
+static int debug = 0;
+
+/* ---------------------------------------------------------------------- */
+
+enum {
+ /* browse */
+ ST_COL_NAME = 0,
+ ST_COL_TYPE,
+ ST_COL_DOMAIN,
+ ST_COL_INTERFACE,
+ ST_COL_PROTOCOL,
+
+ /* resolve */
+ ST_COL_HOSTNAME,
+ ST_COL_ADDR,
+ ST_COL_PORT,
+ ST_COL_PATH,
+
+ /* other */
+ ST_COL_URL,
+
+ ST_NUM_COLS
+};
+
+struct mdns_window {
+ GtkListStore *store;
+ GtkWidget *toplevel, *view, *status;
+ int standalone;
+
+ const AvahiPoll *poll_api;
+ AvahiGLibPoll *glib_poll;
+ AvahiClient *client;
+ AvahiServiceBrowser *sb;
+};
+
/* ---------------------------------------------------------------------- */
static const char *revents[] = {
@@ -32,27 +74,108 @@ static const char *bevents[] = {
[ AVAHI_BROWSER_FAILURE ] = "FAILURE",
};
-static const AvahiPoll *poll_api;
-static AvahiGLibPoll *glib_poll;
-static AvahiClient *client;
-
-struct mdns_entry {
- const char *name;
- const char *type;
- const char *domain;
- AvahiIfIndex interface;
- AvahiProtocol protocol;
-
- const char *address;
- const char *hostname;
- uint16_t port;
-
- struct list_head next;
-};
-static LIST_HEAD(mdns_entries);
+/* ---------------------------------------------------------------------- */
+
+static int find_entry(struct mdns_window *mdns, GtkTreeIter *iter,
+ const char *sname, const char *stype, const char *sdomain,
+ const char *sproto, const char *snif)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL(mdns->store);
+ gboolean valid;
+ char *name, *type, *domain, *proto, *nif;
+
+ for (valid = gtk_tree_model_get_iter_first(model, iter);
+ valid;
+ valid = gtk_tree_model_iter_next(model, iter))
+ {
+ gtk_tree_model_get(model, iter,
+ ST_COL_NAME, &name,
+ ST_COL_TYPE, &type,
+ ST_COL_DOMAIN, &domain,
+ ST_COL_PROTOCOL, &proto,
+ ST_COL_INTERFACE, &nif,
+ -1);
+ if (0 == strcmp(name, sname) &&
+ 0 == strcmp(type, stype) &&
+ 0 == strcmp(domain, sdomain) &&
+ 0 == strcmp(proto, sproto) &&
+ 0 == strcmp(nif, snif))
+ return 0;
+ }
+ return -1;
+}
+
+static void get_entry(struct mdns_window *mdns, GtkTreeIter *iter,
+ const char *sname, const char *stype, const char *sdomain,
+ const char *sproto, const char *snif)
+{
+ if (0 == find_entry(mdns, iter, sname, stype, sdomain, sproto, snif))
+ return;
+ gtk_list_store_append(mdns->store, iter);
+ gtk_list_store_set(mdns->store, iter,
+ ST_COL_NAME, sname,
+ ST_COL_TYPE, stype,
+ ST_COL_DOMAIN, sdomain,
+ ST_COL_PROTOCOL, sproto,
+ ST_COL_INTERFACE, snif,
+ -1);
+ if (debug)
+ fprintf(stderr, "add: %s: %s\n",stype, sname);
+}
+
+static void del_entry(struct mdns_window *mdns,
+ const char *sname, const char *stype, const char *sdomain,
+ const char *sproto, const char *snif)
+{
+ GtkTreeIter iter;
+
+ if (0 == find_entry(mdns, &iter, sname, stype, sdomain, sproto, snif))
+ return;
+ gtk_list_store_remove(mdns->store, &iter);
+ if (debug)
+ fprintf(stderr, "del: %s: %s\n", stype, sname);
+}
+
+static void del_entries(struct mdns_window *mdns)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL(mdns->store);
+ GtkTreeIter iter;
+
+ while (gtk_tree_model_get_iter_first(model, &iter))
+ gtk_list_store_remove(mdns->store, &iter);
+}
/* ---------------------------------------------------------------------- */
+static void ifname(char *dst, int len, int nif)
+{
+#ifdef SIOCGIFNAME
+ struct ifreq ifr;
+ int fd;
+
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0)
+ goto fallback;
+
+ ifr.ifr_ifindex = nif;
+ if (ioctl (fd, SIOCGIFNAME, &ifr) < 0) {
+ close (fd);
+ goto fallback;
+ }
+ snprintf(dst, len, "%s", ifr.ifr_name);
+ close (fd);
+ return;
+
+ fallback:
+#endif
+
+ if (-1 == nif) {
+ snprintf(dst, len, "wide");
+ return;
+ }
+ snprintf(dst, len, "if-%d", nif);
+}
+
static void resolve_callback(AvahiServiceResolver *r,
AvahiIfIndex interface,
AvahiProtocol protocol,
@@ -67,19 +190,66 @@ static void resolve_callback(AvahiServiceResolver *r,
AvahiLookupResultFlags flags,
void* userdata)
{
- struct mdns_entry *e = userdata;
- char a[AVAHI_ADDRESS_STR_MAX];
+ static const struct {
+ char *type;
+ char *proto;
+ int defport;
+ } protos[] = {
+ { "_http._tcp", "http", 80 },
+ { "_ftp._tcp", "ftp", 21 },
+ };
+ struct mdns_window *mdns = userdata;
+ char a[AVAHI_ADDRESS_STR_MAX], p[32], url[256];
+ unsigned char *path = NULL;
+ char *proto = NULL;
+ AvahiStringList *pathlist;
+ GtkTreeIter iter;
+ char nif[32];
+ int defport, i;
switch (event) {
case AVAHI_RESOLVER_FOUND:
+ ifname(nif, sizeof(nif), interface);
+ if (0 != find_entry(mdns, &iter, name, type, domain,
+ avahi_proto_to_string(protocol), nif))
+ break;
avahi_address_snprint(a, sizeof(a), address);
- e->address = strdup(a);
- e->hostname = strdup(host_name);
- e->port = port;
- fprintf(stderr, "%s @ %s: %s | %s if #%d | %s:%d (%s)\n",
- e->type, e->domain, e->name,
- avahi_proto_to_string(e->protocol), e->interface,
- e->address, e->port, e->hostname);
+ snprintf(p, sizeof(p), "%d", port);
+ gtk_list_store_set(mdns->store, &iter,
+ ST_COL_HOSTNAME, host_name,
+ ST_COL_ADDR, a,
+ ST_COL_PORT, p,
+ -1);
+
+ /* path */
+ pathlist = avahi_string_list_find(txt, "path");
+ if (pathlist)
+ path = avahi_string_list_get_text(pathlist);
+ if (!path)
+ break;
+ gtk_list_store_set(mdns->store, &iter,
+ ST_COL_PATH, path+5,
+ -1);
+
+ /* url */
+ for (i = 0; i < sizeof(protos)/sizeof(protos[0]); i++) {
+ if (0 != strcmp(protos[i].type, type))
+ continue;
+ proto = protos[i].proto;
+ defport = protos[i].defport;
+ break;
+ }
+ if (!proto)
+ break;
+ if (defport != port)
+ snprintf(url, sizeof(url), "%s://%s:%d%s",
+ proto, host_name, port, path+5);
+ else
+ snprintf(url, sizeof(url), "%s://%s%s",
+ proto, host_name, path+5);
+ gtk_list_store_set(mdns->store, &iter,
+ ST_COL_URL, url,
+ -1);
break;
default:
fprintf(stderr, "%s: %s (#%d)\n", __FUNCTION__,
@@ -99,29 +269,29 @@ static void browse_callback(AvahiServiceBrowser *b,
AvahiLookupResultFlags flags,
void* userdata)
{
- AvahiClient *c = userdata;
- struct mdns_entry *e;
+ struct mdns_window *mdns = userdata;
+ GtkTreeIter iter;
+ char nif[32];
+
+ ifname(nif, sizeof(nif), interface);
switch (event) {
case AVAHI_BROWSER_NEW:
- e = malloc(sizeof(*e));
- memset(e,0,sizeof(*e));
- e->name = strdup(name);
- e->type = strdup(type);
- e->domain = strdup(domain);
- e->interface = interface;
- e->protocol = protocol;
- list_add_tail(&e->next, &mdns_entries);
- avahi_service_resolver_new(c, interface, protocol, name, type, domain,
- AVAHI_PROTO_UNSPEC, 0, resolve_callback, e);
+ get_entry(mdns, &iter, name, type, domain,
+ avahi_proto_to_string(protocol), nif);
+ avahi_service_resolver_new(mdns->client,
+ interface, protocol, name, type, domain,
+ AVAHI_PROTO_UNSPEC, 0,
+ resolve_callback, mdns);
break;
case AVAHI_BROWSER_REMOVE:
- fprintf(stderr, "%s: DEL: service '%s' of type '%s' in domain '%s'\n",
- __FUNCTION__, name, type, domain);
+ del_entry(mdns, name, type, domain,
+ avahi_proto_to_string(protocol), nif);
break;
default:
- fprintf(stderr, "%s: %s (#%d)\n", __FUNCTION__,
- bevents[event], event);
+ if (debug)
+ fprintf(stderr, "%s: %s (#%d)\n", __FUNCTION__,
+ bevents[event], event);
break;
}
}
@@ -129,80 +299,419 @@ static void browse_callback(AvahiServiceBrowser *b,
static void
client_callback(AvahiClient *client, AvahiClientState state, void *userdata)
{
+// struct mdns_window *mdns = userdata;
+
switch (state) {
case AVAHI_CLIENT_FAILURE:
fprintf(stderr, "%s: error: connection lost\n", __FUNCTION__);
break;
default:
- fprintf(stderr, "%s: state %d\n", __FUNCTION__, state);
+ if (debug)
+ fprintf(stderr, "%s: state %d\n", __FUNCTION__, state);
+ break;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void service_type_browser_callback(AvahiServiceTypeBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *type,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void *userdata)
+{
+ char nif[32];
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ ifname(nif, sizeof(nif), interface);
+ fprintf(stderr, " service: %s, %s, %s: %s\n",
+ nif, avahi_proto_to_string(protocol), domain, type);
+ break;
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_FAILURE:
+ avahi_service_type_browser_free(b);
+ break;
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ /* don't log */
+ break;
+ default:
+ fprintf(stderr, "%s: %s (#%d)\n", __FUNCTION__,
+ bevents[event], event);
+ break;
+ }
+}
+
+static void domain_browser_callback(AvahiDomainBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void *userdata)
+{
+ struct mdns_window *mdns = userdata;
+ char nif[32];
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ ifname(nif, sizeof(nif), interface);
+ fprintf(stderr, " domain : %s, %s, %s\n",
+ nif, avahi_proto_to_string(protocol), domain);
+ avahi_service_type_browser_new(mdns->client,
+ interface, protocol, domain,
+ 0, service_type_browser_callback, mdns);
+ break;
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_FAILURE:
+ avahi_domain_browser_free(b);
+ break;
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ /* don't log */
+ break;
+ default:
+ fprintf(stderr, "%s: %s (#%d)\n", __FUNCTION__,
+ bevents[event], event);
break;
}
}
+static void dump_stuff(struct mdns_window *mdns)
+{
+ const char *domain;
+
+ /* playground ... */
+ domain = avahi_client_get_domain_name(mdns->client);
+ fprintf(stderr, "default domain is \"%s\"\n", domain);
+ avahi_service_type_browser_new(mdns->client,
+ AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, domain,
+ 0, service_type_browser_callback, mdns);
+ avahi_domain_browser_new(mdns->client,
+ AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL,
+ AVAHI_DOMAIN_BROWSER_BROWSE,
+ 0, domain_browser_callback, mdns);
+}
+
/* ---------------------------------------------------------------------- */
-int mdns_init(void)
+static void mdns_fini(struct mdns_window *mdns)
+{
+ if (mdns->client) {
+ if (debug)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ avahi_client_free(mdns->client);
+ mdns->client = NULL;
+ }
+ if (mdns->glib_poll) {
+ avahi_glib_poll_free(mdns->glib_poll);
+ mdns->glib_poll = NULL;
+ }
+}
+
+static int mdns_init(struct mdns_window *mdns)
{
int error;
+ if (mdns->client)
+ return 0;
+ if (debug)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
/* Create the GLIB Adaptor */
avahi_set_allocator(avahi_glib_allocator());
- glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
- poll_api = avahi_glib_poll_get(glib_poll);
- client = avahi_client_new(poll_api, AVAHI_CLIENT_NO_FAIL,
- client_callback, NULL /* user data */,
- &error);
- if (client == NULL)
+ mdns->glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
+ mdns->poll_api = avahi_glib_poll_get(mdns->glib_poll);
+ mdns->client = avahi_client_new(mdns->poll_api, AVAHI_CLIENT_NO_FAIL,
+ client_callback, mdns,
+ &error);
+ if (mdns->client == NULL)
goto fail;
+
+ if (0)
+ dump_stuff(mdns);
return 0;
fail:
- mdns_fini();
+ mdns_fini(mdns);
return -1;
}
-int mdns_browse(const char *service, const char *domain)
+int mdns_browse(struct mdns_window *mdns,
+ const char *service, const char *domain)
{
- AvahiServiceBrowser *sb = NULL;
+ char label[256];
+
+ if (mdns->sb) {
+ avahi_service_browser_free(mdns->sb);
+ mdns->sb = NULL;
+ del_entries(mdns);
+ gtk_label_set_text(GTK_LABEL(mdns->status), "idle");
+ }
if (NULL == domain)
- domain = avahi_client_get_domain_name(client);
- sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
- service, domain, 0, browse_callback, client);
- if (NULL == sb) {
+ domain = avahi_client_get_domain_name(mdns->client);
+ mdns->sb = avahi_service_browser_new(mdns->client,
+ AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ service, domain, 0,
+ browse_callback, mdns);
+ if (NULL == mdns->sb) {
fprintf(stderr, "%s: failed to create service browser: %s\n",
- __FUNCTION__, avahi_strerror(avahi_client_errno(client)));
+ __FUNCTION__, avahi_strerror(avahi_client_errno(mdns->client)));
return -1;
}
+ snprintf(label, sizeof(label),
+ "service \"%s\" in domain \"%s\"",
+ service, domain);
+ gtk_label_set_text(GTK_LABEL(mdns->status), label);
return 0;
}
-void mdns_fini(void)
+/* ---------------------------------------------------------------------- */
+
+static void menu_cb_close(GtkWidget *whatever, gpointer userdata)
+{
+ struct mdns_window *mdns = userdata;
+
+ gtk_widget_destroy(mdns->toplevel);
+}
+
+static void destroy(GtkWidget *widget,
+ gpointer data)
+{
+ struct mdns_window *mdns = data;
+
+ mdns_fini(mdns);
+ g_object_unref(mdns->store);
+ if (mdns->standalone)
+ gtk_main_quit();
+ free(mdns);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const GtkActionEntry entries[] = {
+ {
+ .name = "FileMenu",
+ .label = "_File",
+ },{
+ .name = "Close",
+ .stock_id = GTK_STOCK_CLOSE,
+ .label = "_Close",
+ .accelerator = "<control>Q",
+ .callback = G_CALLBACK(menu_cb_close),
+ },
+};
+
+static char ui_xml[] =
+"<ui>"
+" <menubar name='MainMenu'>"
+" <menu action='FileMenu'>"
+" <menuitem action='Close'/>"
+" </menu>"
+" </menubar>"
+" <toolbar action='ToolBar'>"
+" <toolitem action='Close'/>"
+" </toolbar>"
+"</ui>";
+
+/* ------------------------------------------------------------------ */
+
+static GtkWidget *mdns_create_view(struct mdns_window *mdns)
+{
+ GtkCellRenderer *renderer;
+ GtkWidget *view;
+
+ view = gtk_tree_view_new();
+ gtk_tree_view_set_model(GTK_TREE_VIEW(view),
+ GTK_TREE_MODEL(mdns->store));
+ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
+ GTK_SELECTION_SINGLE);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "name", renderer,
+ "text", ST_COL_NAME,
+ NULL);
+
+#if 0
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "type", renderer,
+ "text", ST_COL_TYPE,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "domain", renderer,
+ "text", ST_COL_DOMAIN,
+ NULL);
+#endif
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "if", renderer,
+ "text", ST_COL_INTERFACE,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "proto", renderer,
+ "text", ST_COL_PROTOCOL,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "hostname", renderer,
+ "text", ST_COL_HOSTNAME,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ g_object_set(renderer,
+ "xalign", 1.0,
+ NULL);
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "address", renderer,
+ "text", ST_COL_ADDR,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "port", renderer,
+ "text", ST_COL_PORT,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "path", renderer,
+ "text", ST_COL_PATH,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "url", renderer,
+ "text", ST_COL_URL,
+ NULL);
+
+ /* fill remaining space */
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, "", renderer,
+ NULL);
+
+ return view;
+}
+
+struct mdns_window *mdns_create_window(int standalone)
{
- if (client) {
- avahi_client_free(client);
- client = NULL;
+ struct mdns_window *mdns;
+ GtkWidget *vbox, *menubar, *toolbar, *scroll;
+ GtkAccelGroup *accel;
+ GtkActionGroup *ag;
+ GtkUIManager *ui;
+ GError *err;
+
+ mdns = malloc(sizeof(*mdns));
+ memset(mdns,0,sizeof(*mdns));
+ if (-1 == mdns_init(mdns)) {
+ free(mdns);
+ return NULL;
}
- if (glib_poll) {
- avahi_glib_poll_free(glib_poll);
- glib_poll = NULL;
+ mdns->standalone = standalone;
+
+ mdns->toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(mdns->toplevel), "mdns");
+ gtk_widget_set_size_request(GTK_WIDGET(mdns->toplevel), 480, 320);
+ g_signal_connect(G_OBJECT(mdns->toplevel), "destroy",
+ G_CALLBACK(destroy), mdns);
+
+ /* menu + toolbar */
+ ui = gtk_ui_manager_new();
+ ag = gtk_action_group_new("MenuActions");
+ gtk_action_group_add_actions(ag, entries, G_N_ELEMENTS(entries), mdns);
+ gtk_ui_manager_insert_action_group(ui, ag, 0);
+ accel = gtk_ui_manager_get_accel_group(ui);
+ gtk_window_add_accel_group(GTK_WINDOW(mdns->toplevel), accel);
+
+ err = NULL;
+ if (!gtk_ui_manager_add_ui_from_string(ui, ui_xml, -1, &err)) {
+ g_message("building menus failed: %s", err->message);
+ g_error_free(err);
+ exit(1);
}
+
+ /* list */
+ mdns->store = gtk_list_store_new(ST_NUM_COLS,
+ G_TYPE_STRING, // ST_COL_NAME
+ G_TYPE_STRING, // ST_COL_TYPE
+ G_TYPE_STRING, // ST_COL_DOMAIN
+ G_TYPE_STRING, // ST_COL_INTERFACE
+ G_TYPE_STRING, // ST_COL_PROTOCOL
+
+ G_TYPE_STRING, // ST_COL_HOSTNAME
+ G_TYPE_STRING, // ST_COL_ADDR
+ G_TYPE_STRING, // ST_COL_PORT
+ G_TYPE_STRING, // ST_COL_PATH
+
+ G_TYPE_STRING); // ST_COL_URL
+ mdns->view = mdns_create_view(mdns);
+#if 0
+ g_signal_connect(mdns->view, "row-activated", G_CALLBACK(activate), mdns);
+#endif
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+
+ /* other widgets */
+ mdns->status = gtk_widget_new(GTK_TYPE_LABEL,
+ "label", "status line",
+ "xalign", 0.0,
+ NULL);
+
+ /* Make a vbox and put stuff in */
+ vbox = gtk_vbox_new(FALSE, 1);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 1);
+ gtk_container_add(GTK_CONTAINER(mdns->toplevel), vbox);
+ menubar = gtk_ui_manager_get_widget(ui, "/MainMenu");
+ gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
+ toolbar = gtk_ui_manager_get_widget(ui, "/ToolBar");
+ gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
+ gtk_container_add(GTK_CONTAINER(scroll), mdns->view);
+ gtk_box_pack_end(GTK_BOX(vbox), mdns->status, FALSE, TRUE, 0);
+
+ return mdns;
}
-#else
+void mdns_show_window(struct mdns_window *mdns)
+{
+ gtk_widget_show_all(mdns->toplevel);
+}
-int mdns_init(void)
+void mdns_destroy_window(struct mdns_window *mdns)
{
- return -1;
+ gtk_widget_destroy(mdns->toplevel);
}
-int mdns_browse(const char *service, const char *domain)
+/* ---------------------------------------------------------------------- */
+
+#else /* ! HAVE_AVAHI */
+
+struct mdns_window *mdns_create_window(void)
{
- return -1;
+ return NULL;
}
-void mdns_fini(void)
+void mdns_show_window(struct mdns_window *mdns) {}
+void mdns_destroy_window(struct mdns_window *mdns) {}
+
+int mdns_browse(struct mdns_window *mdns,
+ const char *service, const char *domain)
{
+ return -1;
}
#endif