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