1 /*
2 * Copyright (C) 2005 Marc Pavot <marc.pavot@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20 #include "widgets/ario-connection-widget.h"
21 #include <config.h>
22 #include <gtk/gtk.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <glib/gi18n.h>
27
28 #ifdef ENABLE_AVAHI
29 #include "ario-avahi.h"
30 #endif
31 #include "ario-debug.h"
32 #include "ario-profiles.h"
33 #include "ario-util.h"
34 #include "lib/gtk-builder-helpers.h"
35 #include "servers/ario-server.h"
36
37 static void ario_connection_widget_finalize (GObject *object);
38 G_MODULE_EXPORT void ario_connection_widget_name_changed_cb (GtkWidget *widget,
39 ArioConnectionWidget *connection_widget);
40 G_MODULE_EXPORT void ario_connection_widget_host_changed_cb (GtkWidget *widget,
41 ArioConnectionWidget *connection_widget);
42 G_MODULE_EXPORT void ario_connection_widget_port_changed_cb (GtkWidget *widget,
43 ArioConnectionWidget *connection_widget);
44 G_MODULE_EXPORT void ario_connection_widget_timeout_changed_cb (GtkWidget *widget,
45 ArioConnectionWidget *connection_widget);
46 G_MODULE_EXPORT void ario_connection_widget_type_changed_cb (GtkToggleAction *toggleaction,
47 ArioConnectionWidget *connection_widget);
48 G_MODULE_EXPORT void ario_connection_widget_password_changed_cb (GtkWidget *widget,
49 ArioConnectionWidget *connection_widget);
50 G_MODULE_EXPORT void ario_connection_widget_local_changed_cb (GtkWidget *widget,
51 ArioConnectionWidget *connection_widget);
52 G_MODULE_EXPORT void ario_connection_widget_musicdir_changed_cb (GtkWidget *widget,
53 ArioConnectionWidget *connection_widget);
54 G_MODULE_EXPORT void ario_connection_widget_autodetect_cb (GtkWidget *widget,
55 ArioConnectionWidget *connection_widget);
56 G_MODULE_EXPORT void ario_connection_widget_open_cb (GtkWidget *widget,
57 ArioConnectionWidget *connection_widget);
58 G_MODULE_EXPORT void ario_connection_widget_new_profile_cb (GtkWidget *widget,
59 ArioConnectionWidget *connection_widget);
60 G_MODULE_EXPORT void ario_connection_widget_delete_profile_cb (GtkWidget *widget,
61 ArioConnectionWidget *connection_widget);
62
63 enum
64 {
65 PROFILE_CHANGED,
66 LAST_SIGNAL
67 };
68
69 static guint ario_connection_widget_signals[LAST_SIGNAL] = { 0 };
70
71 struct ArioConnectionWidgetPrivate
72 {
73 GtkListStore *profile_model;
74 GtkTreeSelection *profile_selection;
75 GSList *profiles;
76 ArioProfile *current_profile;
77
78 GtkWidget *name_entry;
79 GtkWidget *host_entry;
80 GtkWidget *port_spinbutton;
81 GtkWidget *timeout_spinbutton;
82 GtkWidget *password_entry;
83 GtkWidget *local_checkbutton;
84 GtkWidget *musicdir_entry;
85 GtkWidget *musicdir_hbox;
86 GtkWidget *musicdir_label;
87 GtkWidget *autodetect_button;
88 GtkWidget *mpd_radiobutton;
89 GtkWidget *xmms_radiobutton;
90 GtkListStore *autodetect_model;
91 GtkTreeSelection *autodetect_selection;
92 };
93
94
95 enum
96 {
97 NAME_COLUMN,
98 HOST_COLUMN,
99 PORT_COLUMN,
100 N_COLUMN
101 };
102
103 #define ARIO_CONNECTION_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_ARIO_CONNECTION_WIDGET, ArioConnectionWidgetPrivate))
G_DEFINE_TYPE(ArioConnectionWidget,ario_connection_widget,GTK_TYPE_BOX)104 G_DEFINE_TYPE (ArioConnectionWidget, ario_connection_widget, GTK_TYPE_BOX)
105
106 static void
107 ario_connection_widget_class_init (ArioConnectionWidgetClass *klass)
108 {
109 ARIO_LOG_FUNCTION_START;
110 GObjectClass *object_class = G_OBJECT_CLASS (klass);
111
112 /* Signals */
113 ario_connection_widget_signals[PROFILE_CHANGED] =
114 g_signal_new ("profile_changed",
115 G_OBJECT_CLASS_TYPE (object_class),
116 G_SIGNAL_RUN_LAST,
117 G_STRUCT_OFFSET (ArioConnectionWidgetClass, profile_changed),
118 NULL, NULL,
119 g_cclosure_marshal_VOID__VOID,
120 G_TYPE_NONE,
121 0);
122
123 /* Virtual methods */
124 object_class->finalize = ario_connection_widget_finalize;
125
126 /* Private attributes */
127 g_type_class_add_private (klass, sizeof (ArioConnectionWidgetPrivate));
128 }
129
130 static void
ario_connection_widget_init(ArioConnectionWidget * connection_widget)131 ario_connection_widget_init (ArioConnectionWidget *connection_widget)
132 {
133 ARIO_LOG_FUNCTION_START;
134 connection_widget->priv = ARIO_CONNECTION_WIDGET_GET_PRIVATE (connection_widget);
135
136 connection_widget->priv->current_profile = NULL;
137 }
138
139 /* Return TRUE if the profile has changed */
140 static gboolean
ario_connection_widget_profile_selection_update(ArioConnectionWidget * connection_widget,gboolean force_update)141 ario_connection_widget_profile_selection_update (ArioConnectionWidget *connection_widget,
142 gboolean force_update)
143 {
144 ARIO_LOG_FUNCTION_START;
145 ArioProfile *profile = NULL;
146 GList *paths;
147 gint *indices;
148 GtkTreeModel *model = GTK_TREE_MODEL (connection_widget->priv->profile_model);
149 GSList *tmp = connection_widget->priv->profiles;
150 int i;
151
152 /* Get selected row */
153 paths = gtk_tree_selection_get_selected_rows (connection_widget->priv->profile_selection,
154 &model);
155 if (!paths)
156 return FALSE;
157
158 /* Get the profile corresponding to selected row */
159 indices = gtk_tree_path_get_indices ((GtkTreePath *) paths->data);
160 for (i = 0; i < indices[0] && tmp; ++i) {
161 tmp = g_slist_next (tmp);
162 }
163 g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL);
164 g_list_free (paths);
165
166 if (!tmp)
167 return FALSE;
168
169 profile = (ArioProfile *) tmp->data;
170 if (!force_update && connection_widget->priv->current_profile == profile)
171 return FALSE;
172
173 /* Change the current profile to the selected one */
174 connection_widget->priv->current_profile = profile;
175 ario_profiles_set_current (connection_widget->priv->profiles, profile);
176
177
178 /* Block a few signals */
179 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->name_entry),
180 G_CALLBACK (ario_connection_widget_name_changed_cb),
181 connection_widget);
182
183 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->host_entry),
184 G_CALLBACK (ario_connection_widget_host_changed_cb),
185 connection_widget);
186
187 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->port_spinbutton),
188 G_CALLBACK (ario_connection_widget_port_changed_cb),
189 connection_widget);
190
191 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->timeout_spinbutton),
192 G_CALLBACK (ario_connection_widget_timeout_changed_cb),
193 connection_widget);
194
195 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->mpd_radiobutton),
196 G_CALLBACK (ario_connection_widget_type_changed_cb),
197 connection_widget);
198
199 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->password_entry),
200 G_CALLBACK (ario_connection_widget_password_changed_cb),
201 connection_widget);
202
203 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->musicdir_entry),
204 G_CALLBACK (ario_connection_widget_musicdir_changed_cb),
205 connection_widget);
206
207 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->local_checkbutton),
208 G_CALLBACK (ario_connection_widget_local_changed_cb),
209 connection_widget);
210
211 /* Change the different widgets with values of the profile */
212 gtk_entry_set_text (GTK_ENTRY (connection_widget->priv->name_entry), profile->name);
213 gtk_entry_set_text (GTK_ENTRY (connection_widget->priv->host_entry), profile->host);
214 gtk_spin_button_set_value (GTK_SPIN_BUTTON (connection_widget->priv->port_spinbutton), (gdouble) profile->port);
215 gtk_spin_button_set_value (GTK_SPIN_BUTTON (connection_widget->priv->timeout_spinbutton), (gdouble) profile->timeout / 1000.0);
216 if (profile->type == ArioServerXmms)
217 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (connection_widget->priv->xmms_radiobutton), TRUE);
218 else
219 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (connection_widget->priv->mpd_radiobutton), TRUE);
220 gtk_entry_set_text (GTK_ENTRY (connection_widget->priv->password_entry), profile->password ? profile->password : "");
221 gtk_entry_set_text (GTK_ENTRY (connection_widget->priv->musicdir_entry), profile->musicdir ? profile->musicdir : "");
222 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (connection_widget->priv->local_checkbutton), profile->local);
223
224 if (profile->local) {
225 gtk_widget_show (connection_widget->priv->musicdir_hbox);
226 gtk_widget_show (connection_widget->priv->musicdir_label);
227 } else {
228 gtk_widget_hide (connection_widget->priv->musicdir_hbox);
229 gtk_widget_hide (connection_widget->priv->musicdir_label);
230 }
231
232 /* Unblock signals */
233 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->name_entry),
234 G_CALLBACK (ario_connection_widget_name_changed_cb),
235 connection_widget);
236
237 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->host_entry),
238 G_CALLBACK (ario_connection_widget_host_changed_cb),
239 connection_widget);
240
241 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->port_spinbutton),
242 G_CALLBACK (ario_connection_widget_port_changed_cb),
243 connection_widget);
244
245 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->timeout_spinbutton),
246 G_CALLBACK (ario_connection_widget_timeout_changed_cb),
247 connection_widget);
248
249 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->mpd_radiobutton),
250 G_CALLBACK (ario_connection_widget_type_changed_cb),
251 connection_widget);
252
253 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->password_entry),
254 G_CALLBACK (ario_connection_widget_password_changed_cb),
255 connection_widget);
256
257 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->musicdir_entry),
258 G_CALLBACK (ario_connection_widget_musicdir_changed_cb),
259 connection_widget);
260
261 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->local_checkbutton),
262 G_CALLBACK (ario_connection_widget_local_changed_cb),
263 connection_widget);
264 return TRUE;
265 }
266
267 static void
ario_connection_widget_profile_selection_changed_cb(GtkTreeSelection * selection,ArioConnectionWidget * connection_widget)268 ario_connection_widget_profile_selection_changed_cb (GtkTreeSelection * selection,
269 ArioConnectionWidget *connection_widget)
270 {
271 ARIO_LOG_FUNCTION_START;
272 if (ario_connection_widget_profile_selection_update (connection_widget, FALSE)) {
273 /* Emit a signal when profile has changed */
274 g_signal_emit (G_OBJECT (connection_widget), ario_connection_widget_signals[PROFILE_CHANGED], 0);
275 }
276 }
277
278 static void
ario_connection_widget_profile_update_profiles(ArioConnectionWidget * connection_widget)279 ario_connection_widget_profile_update_profiles (ArioConnectionWidget *connection_widget)
280 {
281 ARIO_LOG_FUNCTION_START;
282 GSList *tmp;
283 GtkTreeIter iter;
284 ArioProfile *profile;
285 GtkTreeModel *model = GTK_TREE_MODEL (connection_widget->priv->profile_model);
286
287 /* Block profile changement signal */
288 g_signal_handlers_block_by_func (G_OBJECT (connection_widget->priv->profile_selection),
289 G_CALLBACK (ario_connection_widget_profile_selection_changed_cb),
290 connection_widget);
291
292 /* Clear the list of profiles */
293 gtk_list_store_clear (connection_widget->priv->profile_model);
294
295 /* Append the new profiles to the list */
296 for (tmp = connection_widget->priv->profiles; tmp; tmp = g_slist_next (tmp)) {
297 profile = (ArioProfile *) tmp->data;
298 gtk_list_store_append (connection_widget->priv->profile_model, &iter);
299 gtk_list_store_set (connection_widget->priv->profile_model, &iter,
300 0, profile->name,
301 -1);
302 }
303
304 /* Select current profile */
305 gtk_tree_model_get_iter_first (model, &iter);
306 for (tmp = connection_widget->priv->profiles; tmp; tmp = g_slist_next (tmp)) {
307 profile = (ArioProfile *) tmp->data;
308 if (profile->current) {
309 gtk_tree_selection_select_iter (connection_widget->priv->profile_selection, &iter);
310 break;
311 }
312 gtk_tree_model_iter_next (model, &iter);
313 }
314
315 /* Unblock profile changement signal */
316 g_signal_handlers_unblock_by_func (G_OBJECT (connection_widget->priv->profile_selection),
317 G_CALLBACK (ario_connection_widget_profile_selection_changed_cb),
318 connection_widget);
319 }
320
321 GtkWidget *
ario_connection_widget_new(void)322 ario_connection_widget_new (void)
323 {
324 ARIO_LOG_FUNCTION_START;
325 GtkBuilder *builder;
326 ArioConnectionWidget *connection_widget;
327 GtkWidget *profile_treeview;
328
329 connection_widget = g_object_new (TYPE_ARIO_CONNECTION_WIDGET,
330 NULL);
331
332 g_return_val_if_fail (connection_widget->priv != NULL, NULL);
333 gtk_orientable_set_orientation (GTK_ORIENTABLE (connection_widget), GTK_ORIENTATION_VERTICAL);
334
335 /* Create UI using GtkBuilder */
336 builder = gtk_builder_helpers_new (UI_PATH "connection-widget.ui",
337 connection_widget);
338
339 /* Get pointers to the different widgets */
340 profile_treeview =
341 GTK_WIDGET (gtk_builder_get_object (builder, "profile_treeview"));
342 connection_widget->priv->name_entry =
343 GTK_WIDGET (gtk_builder_get_object (builder, "name_entry"));
344 connection_widget->priv->host_entry =
345 GTK_WIDGET (gtk_builder_get_object (builder, "host_entry"));
346 connection_widget->priv->port_spinbutton =
347 GTK_WIDGET (gtk_builder_get_object (builder, "port_spinbutton"));
348 connection_widget->priv->timeout_spinbutton =
349 GTK_WIDGET (gtk_builder_get_object (builder, "timeout_spinbutton"));
350 connection_widget->priv->password_entry =
351 GTK_WIDGET (gtk_builder_get_object (builder, "password_entry"));
352 connection_widget->priv->local_checkbutton =
353 GTK_WIDGET (gtk_builder_get_object (builder, "local_checkbutton"));
354 connection_widget->priv->musicdir_entry =
355 GTK_WIDGET (gtk_builder_get_object (builder, "musicdir_entry"));
356 connection_widget->priv->musicdir_hbox =
357 GTK_WIDGET (gtk_builder_get_object (builder, "musicdir_hbox"));
358 connection_widget->priv->musicdir_label =
359 GTK_WIDGET (gtk_builder_get_object (builder, "musicdir_label"));
360 connection_widget->priv->autodetect_button =
361 GTK_WIDGET (gtk_builder_get_object (builder, "autodetect_button"));
362 connection_widget->priv->mpd_radiobutton =
363 GTK_WIDGET (gtk_builder_get_object (builder, "mpd_radiobutton"));
364 connection_widget->priv->xmms_radiobutton =
365 GTK_WIDGET (gtk_builder_get_object (builder, "xmms_radiobutton"));
366 connection_widget->priv->profile_model =
367 GTK_LIST_STORE (gtk_builder_get_object (builder, "profile_model"));
368
369 /* Show all widgets except musicdir_box (shown only if Ario is on same computer as
370 * music server */
371 gtk_widget_show_all (connection_widget->priv->musicdir_hbox);
372 gtk_widget_hide (connection_widget->priv->musicdir_hbox);
373 gtk_widget_set_no_show_all (connection_widget->priv->musicdir_hbox, TRUE);
374
375 /* Get the model selection */
376 connection_widget->priv->profile_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (profile_treeview));
377 gtk_tree_selection_set_mode (connection_widget->priv->profile_selection,
378 GTK_SELECTION_BROWSE);
379
380 /* Get the list of profiles */
381 connection_widget->priv->profiles = ario_profiles_get ();
382
383 /* Update the list with profiles */
384 ario_connection_widget_profile_update_profiles (connection_widget);
385
386 #ifndef ENABLE_AVAHI
387 gtk_widget_hide (connection_widget->priv->autodetect_button);
388 #endif
389
390 /* Enable the servertype widgets only if XMMS2 support is activated */
391 #ifndef ENABLE_XMMS2
392 gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder, "servertype_hbox")), FALSE);
393 #endif
394
395 /* Connect signal for profile change */
396 g_signal_connect (connection_widget->priv->profile_selection,
397 "changed",
398 G_CALLBACK (ario_connection_widget_profile_selection_changed_cb),
399 connection_widget);
400 ario_connection_widget_profile_selection_update (connection_widget, FALSE);
401
402 /* Add widgets to ConnectionWidgets */
403 gtk_box_pack_start (GTK_BOX (connection_widget),
404 GTK_WIDGET (gtk_builder_get_object (builder, "hbox")), TRUE, TRUE, 0);
405
406 g_object_unref (builder);
407
408 return GTK_WIDGET (connection_widget);
409 }
410
411 static void
ario_connection_widget_finalize(GObject * object)412 ario_connection_widget_finalize (GObject *object)
413 {
414 ARIO_LOG_FUNCTION_START;
415 ArioConnectionWidget *connection_widget;
416
417 g_return_if_fail (object != NULL);
418 g_return_if_fail (IS_ARIO_CONNECTION_WIDGET (object));
419
420 connection_widget = ARIO_CONNECTION_WIDGET (object);
421
422 g_return_if_fail (connection_widget->priv != NULL);
423
424 /* Save profiles to disk */
425 ario_profiles_save (connection_widget->priv->profiles);
426
427 G_OBJECT_CLASS (ario_connection_widget_parent_class)->finalize (object);
428 }
429
430 void
ario_connection_widget_name_changed_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)431 ario_connection_widget_name_changed_cb (GtkWidget *widget,
432 ArioConnectionWidget *connection_widget)
433 {
434 ARIO_LOG_FUNCTION_START;
435 /* Modify current profile */
436 g_free (connection_widget->priv->current_profile->name);
437 connection_widget->priv->current_profile->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (connection_widget->priv->name_entry)));
438
439 /* Change profile name in the list */
440 ario_connection_widget_profile_update_profiles (connection_widget);
441 }
442
443 void
ario_connection_widget_host_changed_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)444 ario_connection_widget_host_changed_cb (GtkWidget *widget,
445 ArioConnectionWidget *connection_widget)
446 {
447 ARIO_LOG_FUNCTION_START;
448 /* Modify current profile */
449 g_free (connection_widget->priv->current_profile->host);
450 connection_widget->priv->current_profile->host = g_strdup (gtk_entry_get_text (GTK_ENTRY (connection_widget->priv->host_entry)));
451 }
452
453 void
ario_connection_widget_port_changed_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)454 ario_connection_widget_port_changed_cb (GtkWidget *widget,
455 ArioConnectionWidget *connection_widget)
456 {
457 ARIO_LOG_FUNCTION_START;
458 /* Modify current profile */
459 gdouble port = gtk_spin_button_get_value (GTK_SPIN_BUTTON (connection_widget->priv->port_spinbutton));
460 connection_widget->priv->current_profile->port = (int) port;
461 }
462
463 void
ario_connection_widget_timeout_changed_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)464 ario_connection_widget_timeout_changed_cb (GtkWidget *widget,
465 ArioConnectionWidget *connection_widget)
466 {
467 ARIO_LOG_FUNCTION_START;
468 /* Modify current profile */
469 gdouble timeout = gtk_spin_button_get_value (GTK_SPIN_BUTTON (connection_widget->priv->timeout_spinbutton))
470 * 1000.0;
471 connection_widget->priv->current_profile->timeout = (int) timeout;
472 }
473
ario_connection_widget_type_changed_cb(GtkToggleAction * toggleaction,ArioConnectionWidget * connection_widget)474 void ario_connection_widget_type_changed_cb (GtkToggleAction *toggleaction,
475 ArioConnectionWidget *connection_widget)
476
477 {
478 ARIO_LOG_FUNCTION_START;
479 ArioServerType type;
480
481 /* Modify current profile */
482 type = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (connection_widget->priv->xmms_radiobutton)) ? ArioServerXmms : ArioServerMpd;
483 connection_widget->priv->current_profile->type = type;
484 }
485
486 void
ario_connection_widget_password_changed_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)487 ario_connection_widget_password_changed_cb (GtkWidget *widget,
488 ArioConnectionWidget *connection_widget)
489 {
490 ARIO_LOG_FUNCTION_START;
491 const gchar *password;
492
493 /* Modify current profile */
494 password = gtk_entry_get_text (GTK_ENTRY (connection_widget->priv->password_entry));
495 g_free (connection_widget->priv->current_profile->password);
496 if (password && strcmp(password, "")) {
497 connection_widget->priv->current_profile->password = g_strdup (password);
498 } else {
499 connection_widget->priv->current_profile->password = NULL;
500 }
501 }
502
503 void
ario_connection_widget_musicdir_changed_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)504 ario_connection_widget_musicdir_changed_cb (GtkWidget *widget,
505 ArioConnectionWidget *connection_widget)
506 {
507 ARIO_LOG_FUNCTION_START;
508 const gchar *musicdir;
509
510 /* Modify current profile */
511 musicdir = gtk_entry_get_text (GTK_ENTRY (connection_widget->priv->musicdir_entry));
512 g_free (connection_widget->priv->current_profile->musicdir);
513 if (musicdir && strcmp(musicdir, "")) {
514 connection_widget->priv->current_profile->musicdir = g_strdup (musicdir);
515 } else {
516 connection_widget->priv->current_profile->musicdir = NULL;
517 }
518 }
519
520 void
ario_connection_widget_local_changed_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)521 ario_connection_widget_local_changed_cb (GtkWidget *widget,
522 ArioConnectionWidget *connection_widget)
523 {
524 ARIO_LOG_FUNCTION_START;
525 gboolean local;
526
527 /* Modify current profile */
528 local = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (connection_widget->priv->local_checkbutton));
529 connection_widget->priv->current_profile->local = local;
530 if (local) {
531 gtk_widget_show (connection_widget->priv->musicdir_hbox);
532 gtk_widget_show (connection_widget->priv->musicdir_label);
533 } else {
534 gtk_widget_hide (connection_widget->priv->musicdir_hbox);
535 gtk_widget_hide (connection_widget->priv->musicdir_label);
536 }
537 }
538
539 #ifdef ENABLE_AVAHI
540 /* Method called when list of hosts detected by avahi has changed */
541 static void
ario_connection_widget_autohosts_changed_cb(ArioAvahi * avahi,ArioConnectionWidget * connection_widget)542 ario_connection_widget_autohosts_changed_cb (ArioAvahi *avahi,
543 ArioConnectionWidget *connection_widget)
544 {
545 ARIO_LOG_FUNCTION_START;
546 GtkTreeIter iter;
547 GSList *hosts;
548 char tmp[INTLEN];
549
550 /* Clear the hosts lists */
551 gtk_list_store_clear (connection_widget->priv->autodetect_model);
552
553 /* Append all found hosts to the list */
554 for (hosts = ario_avahi_get_hosts (avahi); hosts; hosts = g_slist_next (hosts)) {
555 ArioHost *host = hosts->data;
556 gtk_list_store_append (connection_widget->priv->autodetect_model, &iter);
557 g_snprintf (tmp, INTLEN, "%d", host->port);
558 gtk_list_store_set (connection_widget->priv->autodetect_model, &iter,
559 NAME_COLUMN, host->name,
560 HOST_COLUMN, host->host,
561 PORT_COLUMN, tmp,
562 -1);
563 }
564
565 /* Select first host */
566 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (connection_widget->priv->autodetect_model), &iter))
567 gtk_tree_selection_select_iter (connection_widget->priv->autodetect_selection, &iter);
568 }
569 #endif
570 void
ario_connection_widget_autodetect_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)571 ario_connection_widget_autodetect_cb (GtkWidget *widget,
572 ArioConnectionWidget *connection_widget)
573 {
574 ARIO_LOG_FUNCTION_START;
575 #ifdef ENABLE_AVAHI
576 GtkBuilder *builder;
577 ArioAvahi *avahi;
578 GtkWidget *dialog, *error_dialog;
579 GtkWidget *treeview;
580 GtkTreeModel *treemodel;
581 GtkTreeIter iter;
582 gchar *tmp;
583 gchar *host;
584 int port;
585 gint retval;
586
587 /* Create UI using GtkBuilder */
588 builder = gtk_builder_helpers_new (UI_PATH "connection-autodetect.ui", NULL);
589
590 /* Get pointers to the different widgets */
591 dialog =
592 GTK_WIDGET (gtk_builder_get_object (builder, "dialog"));
593 treeview =
594 GTK_WIDGET (gtk_builder_get_object (builder, "treeview"));
595 connection_widget->priv->autodetect_model =
596 GTK_LIST_STORE (gtk_builder_get_object (builder, "autodetect_model"));
597 g_object_unref (builder);
598
599 /* Create avahi proxy */
600 avahi = ario_avahi_new ();
601
602 /* Get selection */
603 connection_widget->priv->autodetect_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
604 gtk_tree_selection_set_mode (connection_widget->priv->autodetect_selection,
605 GTK_SELECTION_BROWSE);
606
607 /* Connect signal called when avahi detects new hosts */
608 g_signal_connect (avahi,
609 "hosts_changed",
610 G_CALLBACK (ario_connection_widget_autohosts_changed_cb),
611 connection_widget);
612
613 /* Run dialog */
614 gtk_widget_show_all (dialog);
615 retval = gtk_dialog_run (GTK_DIALOG(dialog));
616
617 /* Stop here if pressed button is not OK */
618 if (retval != 1) {
619 gtk_widget_destroy (dialog);
620 g_object_unref (avahi);
621 return;
622 }
623
624 treemodel = GTK_TREE_MODEL (connection_widget->priv->autodetect_model);
625 if (gtk_tree_selection_get_selected (connection_widget->priv->autodetect_selection,
626 &treemodel,
627 &iter)) {
628 /* Get infos about selected host */
629 gtk_tree_model_get (treemodel, &iter,
630 HOST_COLUMN, &host,
631 PORT_COLUMN, &tmp, -1);
632 port = atoi (tmp);
633 g_free (tmp);
634
635 /* Update current profile with avahi info */
636 g_free (connection_widget->priv->current_profile->host);
637 connection_widget->priv->current_profile->host = g_strdup (host);
638 g_free (host);
639 connection_widget->priv->current_profile->port = port;
640 connection_widget->priv->current_profile->timeout = ARIO_DEFAULT_TIMEOUT;
641 g_free (connection_widget->priv->current_profile->password);
642 connection_widget->priv->current_profile->password = NULL;
643 g_free (connection_widget->priv->current_profile->musicdir);
644 connection_widget->priv->current_profile->musicdir = NULL;
645
646 ario_connection_widget_profile_selection_update (connection_widget, TRUE);
647 } else {
648 /* No server selected */
649 error_dialog = gtk_message_dialog_new(NULL,
650 GTK_DIALOG_MODAL,
651 GTK_MESSAGE_ERROR,
652 GTK_BUTTONS_OK,
653 _("You must select a server."));
654 gtk_dialog_run(GTK_DIALOG(error_dialog));
655 gtk_widget_destroy(error_dialog);
656 }
657
658 g_object_unref (avahi);
659 gtk_widget_destroy (dialog);
660 #endif
661 }
662
663 void
ario_connection_widget_open_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)664 ario_connection_widget_open_cb (GtkWidget *widget,
665 ArioConnectionWidget *connection_widget)
666 {
667 ARIO_LOG_FUNCTION_START;
668 GtkWidget *dialog;
669
670 /* Create a dialog to choose the music directory */
671 dialog = gtk_file_chooser_dialog_new (NULL,
672 NULL,
673 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
674 _("_Cancel"), GTK_RESPONSE_CANCEL,
675 _("_Open"), GTK_RESPONSE_ACCEPT,
676 NULL);
677
678 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
679 char *filename;
680
681 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
682 if (filename) {
683 /* Set the text in the entry with choosen path */
684 gtk_entry_set_text (GTK_ENTRY (connection_widget->priv->musicdir_entry), filename);
685 g_free (filename);
686 }
687 }
688
689 gtk_widget_destroy (dialog);
690 }
691
692 void
ario_connection_widget_new_profile_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)693 ario_connection_widget_new_profile_cb (GtkWidget *widget,
694 ArioConnectionWidget *connection_widget)
695 {
696 ARIO_LOG_FUNCTION_START;
697 ArioProfile *profile;
698 ArioProfile *tmp_profile;
699 GSList *tmp;
700
701 /* Create a new profile with default values */
702 profile = (ArioProfile *) g_malloc0 (sizeof (ArioProfile));
703 profile->name = g_strdup (_("New Profile"));
704 profile->host = g_strdup ("localhost");
705 profile->port = 6600;
706 profile->timeout = ARIO_DEFAULT_TIMEOUT;
707 profile->type = ArioServerMpd;
708
709 /* Remove 'current' flag from all profiles */
710 for (tmp = connection_widget->priv->profiles; tmp; tmp = g_slist_next (tmp)) {
711 tmp_profile = (ArioProfile *) tmp->data;
712 tmp_profile->current = FALSE;
713 }
714
715 /* Append new profile to the list */
716 connection_widget->priv->profiles = g_slist_append (connection_widget->priv->profiles, profile);
717
718 /* Set the new profile as current */
719 profile->current = TRUE;
720 ario_connection_widget_profile_update_profiles (connection_widget);
721 ario_connection_widget_profile_selection_update (connection_widget, FALSE);
722
723 /* Notify that current profile has changed */
724 g_signal_emit (G_OBJECT (connection_widget), ario_connection_widget_signals[PROFILE_CHANGED], 0);
725 }
726
727 void
ario_connection_widget_delete_profile_cb(GtkWidget * widget,ArioConnectionWidget * connection_widget)728 ario_connection_widget_delete_profile_cb (GtkWidget *widget,
729 ArioConnectionWidget *connection_widget)
730 {
731 ARIO_LOG_FUNCTION_START;
732 ArioProfile *first_profile;
733
734 /* We need to keep at least one profile */
735 if (g_slist_length (connection_widget->priv->profiles) < 2)
736 return;
737
738 if (connection_widget->priv->current_profile) {
739 /* Remove the profile from the list */
740 connection_widget->priv->profiles = g_slist_remove (connection_widget->priv->profiles, connection_widget->priv->current_profile);
741
742 /* Delete the profile */
743 ario_profiles_free (connection_widget->priv->current_profile);
744
745 /* Set the first profile as the current one */
746 if (connection_widget->priv->profiles) {
747 first_profile = (ArioProfile *) connection_widget->priv->profiles->data;
748 first_profile->current = TRUE;
749 }
750 ario_connection_widget_profile_update_profiles (connection_widget);
751 ario_connection_widget_profile_selection_update (connection_widget, FALSE);
752
753 /* Notify that current profile has changed */
754 g_signal_emit (G_OBJECT (connection_widget), ario_connection_widget_signals[PROFILE_CHANGED], 0);
755 }
756 }
757
758