]> git.sesse.net Git - vlc/blob - modules/gui/pda/pda_callbacks.c
PDA Interface:
[vlc] / modules / gui / pda / pda_callbacks.c
1 /*****************************************************************************
2  * pda_callbacks.c : Callbacks for the pda Linux Gtk+ plugin.
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id: pda_callbacks.c,v 1.19 2003/11/30 11:22:29 jpsaman Exp $
6  *
7  * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <sys/types.h>                                              /* off_t */
28 #include <stdlib.h>
29 #include <vlc/vlc.h>
30 #include <vlc/intf.h>
31 #include <vlc/vout.h>
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <dirent.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 #include <pwd.h>
39 #include <grp.h>
40
41 #ifdef HAVE_CONFIG_H
42 #  include <config.h>
43 #endif
44
45 #include <gtk/gtk.h>
46
47 #include "pda_callbacks.h"
48 #include "pda_interface.h"
49 #include "pda_support.h"
50 #include "pda.h"
51
52 #define VLC_MAX_MRL     256
53
54 static char *get_file_perms(struct stat st);
55
56 /*****************************************************************************
57  * Useful function to retrieve p_intf
58  ****************************************************************************/
59 void * E_(__GtkGetIntf)( GtkWidget * widget )
60 {
61     void *p_data;
62
63     if( GTK_IS_MENU_ITEM( widget ) )
64     {
65         /* Look for a GTK_MENU */
66         while( widget->parent && !GTK_IS_MENU( widget ) )
67         {
68             widget = widget->parent;
69         }
70
71         /* Maybe this one has the data */
72         p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
73         if( p_data )
74         {
75             return p_data;
76         }
77
78         /* Otherwise, the parent widget has it */
79         widget = gtk_menu_get_attach_widget( GTK_MENU( widget ) );
80     }
81
82     /* We look for the top widget */
83     widget = gtk_widget_get_toplevel( GTK_WIDGET( widget ) );
84
85     p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
86
87     return p_data;
88 }
89
90 void PlaylistAddItem(GtkWidget *widget, gchar *name)
91 {
92     intf_thread_t *p_intf = GtkGetIntf( widget );
93     playlist_t    *p_playlist;
94     GtkTreeView   *p_tvplaylist = NULL;
95
96     p_playlist = (playlist_t *)
97              vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
98
99     if( p_playlist ==  NULL)
100     {   /* Bail out when VLC's playlist object is not found. */
101         return;
102     }
103
104     /* Add to playlist object. */
105     p_tvplaylist = (GtkTreeView *) lookup_widget( GTK_WIDGET(widget), "tvPlaylist");
106     if (p_tvplaylist)
107     {
108         GtkTreeModel *p_play_model;
109         GtkTreeIter   p_play_iter;
110
111         p_play_model = gtk_tree_view_get_model(p_tvplaylist);
112
113         if (p_play_model)
114         {
115             /* Add a new row to the playlist treeview model */
116             gtk_list_store_append (GTK_LIST_STORE(p_play_model), &p_play_iter);
117             gtk_list_store_set (GTK_LIST_STORE(p_play_model), &p_play_iter,
118                                     0, name,   /* Add path to it !!! */
119                                     1, "no info",
120                                     2, p_playlist->i_size, /* Hidden index. */
121                                     -1 );
122
123             /* Add to VLC's playlist */
124 #if 0
125             if (p_intf->p_sys->b_autoplayfile)
126             {
127                 playlist_Add( p_playlist, (const char*)name, 0, 0,
128                               PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END);
129             }
130             else
131 #endif
132             {
133                 playlist_Add( p_playlist, (const char*)name, 0, 0,
134                               PLAYLIST_APPEND, PLAYLIST_END );
135             }            
136         }
137     }
138     vlc_object_release( p_playlist );
139 }
140
141 void PlaylistRebuildListStore( GtkListStore * p_list, playlist_t * p_playlist )
142 {
143     GtkTreeIter iter;
144     int         i_dummy;
145     gchar *     ppsz_text[2];
146     GdkColor    red;
147     red.red     = 65535;
148     red.blue    = 0;
149     red.green   = 0;
150
151     vlc_mutex_lock( &p_playlist->object_lock );
152     for( i_dummy = 0; i_dummy < p_playlist->i_size ; i_dummy++ )
153     {
154         ppsz_text[0] = p_playlist->pp_items[i_dummy]->psz_name;
155         ppsz_text[1] = "no info";
156         gtk_list_store_append (p_list, &iter);
157         gtk_list_store_set (p_list, &iter,
158                             0, ppsz_text[0],
159                             1, ppsz_text[1],
160                             2, i_dummy, /* Hidden index */
161                             -1);
162     }
163     vlc_mutex_unlock( &p_playlist->object_lock );
164 }
165
166 /*****************************************************************
167  * Read directory helper function.
168  ****************************************************************/
169 void ReadDirectory(intf_thread_t *p_intf, GtkListStore *p_list, char *psz_dir )
170 {
171     GtkTreeIter    iter;
172     struct dirent **namelist;
173     struct passwd *pw;
174     struct group  *grp;
175     struct stat    st;
176     int n=-1, status=-1;
177
178     msg_Dbg(p_intf, "Changing to dir %s", psz_dir);
179     if (psz_dir)
180     {
181        status = chdir(psz_dir);
182        if (status<0)
183           msg_Dbg(p_intf, "permision denied" );
184     }
185     n = scandir(".", &namelist, 0, alphasort);
186
187     if (n<0)
188         perror("scandir");
189     else
190     {
191         int i;
192         gchar *ppsz_text[4];
193
194         if (lstat("..", &st)==0)
195         {
196             /* user, group  */
197             pw  = getpwuid(st.st_uid);
198             grp = getgrgid(st.st_gid);
199
200             /* XXX : kludge temporaire pour yopy */
201             ppsz_text[0] = "..";
202             ppsz_text[1] = get_file_perms(st);
203             ppsz_text[2] = pw->pw_name;
204             ppsz_text[3] = grp->gr_name;
205
206             /* Add a new row to the model */
207             gtk_list_store_append (p_list, &iter);
208             gtk_list_store_set (p_list, &iter,
209                                 0, ppsz_text[0],
210                                 1, ppsz_text[1],
211                                 2, st.st_size,
212                                 3, ppsz_text[2],
213                                 4, ppsz_text[3],
214                                 -1);
215
216             if (ppsz_text[1]) free(ppsz_text[1]);
217         }
218             /* kludge */
219         for (i=0; i<n; i++)
220         {           
221             if ((namelist[i]->d_name[0] != '.') &&
222                 (lstat(namelist[i]->d_name, &st)==0))
223             {
224                 /* user, group  */
225                 pw  = getpwuid(st.st_uid);
226                 grp = getgrgid(st.st_gid);
227
228                 /* This is a list of strings. */
229                 ppsz_text[0] = namelist[i]->d_name;
230                 ppsz_text[1] = get_file_perms(st);
231                 ppsz_text[2] = pw->pw_name;
232                 ppsz_text[3] = grp->gr_name;
233 #if 0
234                 msg_Dbg(p_intf, "(%d) file: %s permission: %s user: %s group: %s", i, ppsz_text[0], ppsz_text[1], ppsz_text[2], ppsz_text[3] );
235 #endif
236                 gtk_list_store_append (p_list, &iter);
237                 gtk_list_store_set (p_list, &iter,
238                                     0, ppsz_text[0],
239                                     1, ppsz_text[1],
240                                     2, st.st_size,
241                                     3, ppsz_text[2],
242                                     4, ppsz_text[3],
243                                     -1);
244
245                 if (ppsz_text[1]) free(ppsz_text[1]);
246             }
247         }
248         free(namelist);
249     }
250 }
251
252 static char *get_file_perms(const struct stat st)
253 {
254     char  *perm;
255
256     perm = (char *) malloc(sizeof(char)*10);
257     strncpy( perm, "----------", sizeof("----------"));
258
259     /* determine permission modes */
260     if (S_ISLNK(st.st_mode))
261         perm[0]= 'l';
262     else if (S_ISDIR(st.st_mode))
263         perm[0]= 'd';
264     else if (S_ISCHR(st.st_mode))
265         perm[0]= 'c';
266     else if (S_ISBLK(st.st_mode))
267         perm[0]= 'b';
268     else if (S_ISFIFO(st.st_mode))
269         perm[0]= 'f';
270     else if (S_ISSOCK(st.st_mode))
271         perm[0]= 's';
272     else if (S_ISREG(st.st_mode))
273         perm[0]= '-';
274     else /* Unknown type is an error */
275         perm[0]= '?';
276     /* Get file permissions */
277     /* User */
278     if (st.st_mode & S_IRUSR)
279         perm[1]= 'r';
280     if (st.st_mode & S_IWUSR)
281         perm[2]= 'w';
282     if (st.st_mode & S_IXUSR)
283     {
284         if (st.st_mode & S_ISUID)
285             perm[3] = 's';
286         else
287             perm[3]= 'x';
288     }
289     else if (st.st_mode & S_ISUID)
290         perm[3] = 'S';
291     /* Group */
292     if (st.st_mode & S_IRGRP)
293         perm[4]= 'r';
294     if (st.st_mode & S_IWGRP)
295         perm[5]= 'w';
296     if (st.st_mode & S_IXGRP)
297     {
298         if (st.st_mode & S_ISGID)
299             perm[6] = 's';
300         else
301             perm[6]= 'x';
302     }
303     else if (st.st_mode & S_ISGID)
304         perm[6] = 'S';
305     /* Other */
306     if (st.st_mode & S_IROTH)
307         perm[7]= 'r';
308     if (st.st_mode & S_IWOTH)
309         perm[8]= 'w';
310     if (st.st_mode & S_IXOTH)
311     {
312         // 'sticky' bit
313         if (st.st_mode &S_ISVTX)
314             perm[9] = 't';
315         else
316             perm[9]= 'x';
317     }
318     else if (st.st_mode &S_ISVTX)
319         perm[9]= 'T';
320
321     return perm;
322 }
323
324 /*
325  * Main interface callbacks
326  */
327
328 gboolean
329 onPDADeleteEvent                       (GtkWidget       *widget,
330                                         GdkEvent        *event,
331                                         gpointer         user_data)
332 {
333     intf_thread_t *p_intf = GtkGetIntf( widget );
334
335     vlc_mutex_lock( &p_intf->change_lock );
336     p_intf->p_vlc->b_die = VLC_TRUE;
337     vlc_mutex_unlock( &p_intf->change_lock );
338     msg_Dbg( p_intf, "about to exit vlc ... signalled" );
339
340     return TRUE;
341 }
342
343
344 void
345 onRewind                               (GtkButton       *button,
346                                         gpointer         user_data)
347 {
348     intf_thread_t *  p_intf = GtkGetIntf( button );
349
350     if (p_intf->p_sys->p_input != NULL)
351     {
352         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
353     }
354 }
355
356
357 void
358 onPause                                (GtkButton       *button,
359                                         gpointer         user_data)
360 {
361     intf_thread_t *  p_intf = GtkGetIntf( button );
362
363     if (p_intf->p_sys->p_input != NULL)
364     {
365         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
366     }
367 }
368
369
370 void
371 onPlay                                 (GtkButton       *button,
372                                         gpointer         user_data)
373 {
374     intf_thread_t *  p_intf = GtkGetIntf( GTK_WIDGET( button ) );
375     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
376
377     if (p_playlist)
378     {
379         vlc_mutex_lock( &p_playlist->object_lock );
380         if (p_playlist->i_size)
381         {
382             vlc_mutex_unlock( &p_playlist->object_lock );
383             playlist_Play( p_playlist );
384         }
385         else
386         {
387             vlc_mutex_unlock( &p_playlist->object_lock );
388         }
389         vlc_object_release( p_playlist );
390     }
391 }
392
393
394 void
395 onStop                                 (GtkButton       *button,
396                                         gpointer         user_data)
397 {
398     intf_thread_t *  p_intf = GtkGetIntf( GTK_WIDGET( button ) );
399     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
400                                                        FIND_ANYWHERE );
401     if (p_playlist)
402     {
403         playlist_Stop( p_playlist );
404         vlc_object_release( p_playlist );
405     }
406 }
407
408
409 void
410 onForward                              (GtkButton       *button,
411                                         gpointer         user_data)
412 {
413     intf_thread_t *p_intf = GtkGetIntf( button );
414
415     if (p_intf->p_sys->p_input != NULL)
416     {
417         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
418     }
419 }
420
421
422 void
423 onAbout                                (GtkButton       *button,
424                                         gpointer         user_data)
425 {
426     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(button) );
427
428     // Toggle notebook
429     if (p_intf->p_sys->p_notebook)
430     {
431         gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
432         gtk_notebook_set_page(p_intf->p_sys->p_notebook,6);
433     }
434 }
435
436
437 gboolean
438 SliderRelease                          (GtkWidget       *widget,
439                                         GdkEventButton  *event,
440                                         gpointer         user_data)
441 {
442     intf_thread_t *p_intf = GtkGetIntf( widget );
443
444     vlc_mutex_lock( &p_intf->change_lock );
445     p_intf->p_sys->b_slider_free = 1;
446     vlc_mutex_unlock( &p_intf->change_lock );
447
448     return TRUE;
449 }
450
451
452 gboolean
453 SliderPress                            (GtkWidget       *widget,
454                                         GdkEventButton  *event,
455                                         gpointer         user_data)
456 {
457     intf_thread_t *p_intf = GtkGetIntf( widget );
458
459     vlc_mutex_lock( &p_intf->change_lock );
460     p_intf->p_sys->b_slider_free = 0;
461     vlc_mutex_unlock( &p_intf->change_lock );
462
463     return TRUE;
464 }
465
466 void addSelectedToPlaylist(GtkTreeModel *model,
467                                GtkTreePath *path,
468                                GtkTreeIter *iter,
469                                gpointer *userdata)
470 {
471     gchar *filename;
472
473     gtk_tree_model_get(model, iter, 0, &filename, -1);
474
475     PlaylistAddItem(GTK_WIDGET(userdata), filename);
476 }
477
478 void
479 onFileListRow                          (GtkTreeView     *treeview,
480                                         GtkTreePath     *path,
481                                         GtkTreeViewColumn *column,
482                                         gpointer         user_data)
483 {
484     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(treeview) );
485     GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
486
487     if (gtk_tree_selection_count_selected_rows(selection) == 1)
488     {
489         struct stat   st;
490         GtkTreeModel *model;
491         GtkTreeIter   iter;
492         gchar        *filename;
493
494         /* This might be a directory selection */
495         model = gtk_tree_view_get_model(treeview);
496         if (!model)
497         {
498             msg_Err(p_intf, "PDA: Filelist model contains a NULL pointer\n" );
499             return;
500         }
501         if (!gtk_tree_model_get_iter(model, &iter, path))
502         {
503             msg_Err( p_intf, "PDA: Could not get iter from model" );
504             return;
505         }
506
507         gtk_tree_model_get(model, &iter, 0, &filename, -1);
508         if (stat((char*)filename, &st)==0)
509         {
510             if (S_ISDIR(st.st_mode))
511             {
512                 GtkListStore *p_model = NULL;
513
514                 /* Get new directory listing */
515                 p_model = gtk_list_store_new (5,
516                                            G_TYPE_STRING,
517                                            G_TYPE_STRING,
518                                            G_TYPE_UINT64,
519                                            G_TYPE_STRING,
520                                            G_TYPE_STRING);
521                 if (p_model)
522                 {
523                     ReadDirectory(p_intf, p_model, filename);
524
525                     /* Update TreeView with new model */
526                     gtk_tree_view_set_model(treeview, (GtkTreeModel*) p_model);
527                     g_object_unref(p_model);
528                 }
529             }
530             else
531             {
532                 gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) &addSelectedToPlaylist, (gpointer) treeview);
533             }
534         }
535     }
536     else
537     {
538         gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) &addSelectedToPlaylist, (gpointer) treeview);
539     }
540 }
541
542 void
543 onAddFileToPlaylist                    (GtkButton       *button,
544                                         gpointer         user_data)
545 {
546     GtkTreeView       *treeview = NULL;
547
548     treeview = (GtkTreeView *) lookup_widget( GTK_WIDGET(button), "tvFileList");
549     if (treeview)
550     {
551         GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
552
553         gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) &addSelectedToPlaylist, (gpointer) treeview);    
554     }
555 }
556
557
558 void
559 NetworkBuildMRL                        (GtkEditable     *editable,
560                                         gpointer         user_data)
561 {
562     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(editable) );
563     GtkSpinButton *networkPort = NULL;
564     GtkEntry      *entryMRL = NULL;
565     GtkEntry      *networkType = NULL;
566     GtkEntry      *networkAddress = NULL;
567     GtkEntry      *networkProtocol = NULL;
568     const gchar   *mrlNetworkType;
569     const gchar   *mrlAddress;
570     const gchar   *mrlProtocol;
571     gint           mrlPort;
572     char           text[VLC_MAX_MRL];
573     int            pos = 0;
574
575     entryMRL = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryMRL" );
576
577     networkType     = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryNetworkType" );
578     networkAddress  = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryNetworkAddress" );
579     networkPort     = (GtkSpinButton*) lookup_widget( GTK_WIDGET(editable), "entryNetworkPort" );
580     networkProtocol = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryNetworkProtocolType" );
581
582     mrlNetworkType = gtk_entry_get_text(GTK_ENTRY(networkType));
583     mrlAddress     = gtk_entry_get_text(GTK_ENTRY(networkAddress));
584     mrlPort        = gtk_spin_button_get_value_as_int(networkPort);
585     mrlProtocol    = gtk_entry_get_text(GTK_ENTRY(networkProtocol));
586
587     /* Build MRL from parts ;-) */
588     pos = snprintf( &text[0], VLC_MAX_MRL, "%s://", (char*)mrlProtocol);
589     if (strncasecmp( (char*)mrlNetworkType, "multicast",9)==0)
590     {
591         pos += snprintf( &text[pos], VLC_MAX_MRL - pos, "@" );
592     }
593     pos += snprintf( &text[pos], VLC_MAX_MRL - pos, "%s:%d", (char*)mrlAddress, (int)mrlPort );
594
595     if (pos >= VLC_MAX_MRL)
596     {
597         text[VLC_MAX_MRL-1]='\0';
598         msg_Err( p_intf, "Media Resource Locator is truncated to: %s", text);
599     }
600
601     gtk_entry_set_text(entryMRL,text);
602 }
603
604 void
605 onAddNetworkPlaylist                   (GtkButton       *button,
606                                         gpointer         user_data)
607 {
608     GtkEntry     *p_mrl = NULL;
609     const gchar  *mrl_name;
610
611     p_mrl = (GtkEntry*) lookup_widget(GTK_WIDGET(button),"entryMRL" );
612     if (p_mrl)
613     {
614         mrl_name = gtk_entry_get_text(p_mrl);
615
616         PlaylistAddItem(GTK_WIDGET(button), (gchar *)mrl_name);
617     }
618 }
619
620
621 void
622 onAddCameraToPlaylist                  (GtkButton       *button,
623                                         gpointer         user_data)
624 {
625     intf_thread_t *p_intf = GtkGetIntf( button );
626
627     GtkSpinButton *entryV4LChannel = NULL;
628     GtkSpinButton *entryV4LFrequency = NULL;
629     GtkSpinButton *entryV4LSampleRate = NULL;
630     GtkSpinButton *entryV4LQuality = NULL;
631     GtkSpinButton *entryV4LTuner = NULL;
632     gint    i_v4l_channel;
633     gint    i_v4l_frequency;
634     gint    i_v4l_samplerate;
635     gint    i_v4l_quality;
636     gint    i_v4l_tuner;
637
638     GtkEntry      *entryV4LVideoDevice = NULL;
639     GtkEntry      *entryV4LAudioDevice = NULL;
640     GtkEntry      *entryV4LNorm = NULL;
641     GtkEntry      *entryV4LSize = NULL;
642     GtkEntry      *entryV4LSoundDirection = NULL;
643     const gchar   *p_v4l_video_device;
644     const gchar   *p_v4l_audio_device;
645     const gchar   *p_v4l_norm;
646     const gchar   *p_v4l_size;
647     const gchar   *p_v4l_sound_direction;
648
649     /* MJPEG only */
650     GtkCheckButton *checkV4LMJPEG = NULL;
651     GtkSpinButton  *entryV4LDecimation = NULL;
652     gboolean        b_v4l_mjpeg;
653     gint            i_v4l_decimation;
654     /* end MJPEG only */
655
656     char v4l_mrl[VLC_MAX_MRL];
657     int pos;
658
659     pos = snprintf( &v4l_mrl[0], VLC_MAX_MRL, "v4l://");
660
661     entryV4LChannel    = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LChannel" );
662     entryV4LFrequency  = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LFrequency" );
663     entryV4LSampleRate = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LSampleRate" );
664     entryV4LQuality    = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LQuality" );
665     entryV4LTuner      = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LTuner" );
666
667     entryV4LVideoDevice  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LVideoDevice" );
668     entryV4LAudioDevice  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LAudioDevice" );
669     entryV4LNorm  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LNorm" );
670     entryV4LSize  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LSize" );
671     entryV4LSoundDirection  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LSoundDirection" );
672
673     i_v4l_channel = gtk_spin_button_get_value_as_int(entryV4LChannel);
674     i_v4l_frequency = gtk_spin_button_get_value_as_int(entryV4LFrequency);
675     i_v4l_samplerate = gtk_spin_button_get_value_as_int(entryV4LSampleRate);
676     i_v4l_quality = gtk_spin_button_get_value_as_int(entryV4LQuality);
677     i_v4l_tuner = gtk_spin_button_get_value_as_int(entryV4LTuner);
678
679     p_v4l_video_device = gtk_entry_get_text(GTK_ENTRY(entryV4LVideoDevice));
680     p_v4l_audio_device = gtk_entry_get_text(GTK_ENTRY(entryV4LAudioDevice));
681     p_v4l_norm = gtk_entry_get_text(GTK_ENTRY(entryV4LNorm));
682     p_v4l_size  = gtk_entry_get_text(GTK_ENTRY(entryV4LSize));
683     p_v4l_sound_direction = gtk_entry_get_text(GTK_ENTRY(entryV4LSoundDirection));
684
685     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":%s", (char*)p_v4l_video_device );
686     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":adev=%s", (char*)p_v4l_audio_device );
687     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":norm=%s", (char*)p_v4l_norm );
688     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":size=%s", (char*)p_v4l_size );
689     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":%s", (char*)p_v4l_sound_direction );
690
691     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":channel=%d", (int)i_v4l_channel );
692     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":frequency=%d", (int)i_v4l_frequency );
693     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":samplerate=%d", (int)i_v4l_samplerate );
694     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":quality=%d", (int)i_v4l_quality );
695     pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":tuner=%d", (int)i_v4l_tuner );
696
697     /* MJPEG only */
698     checkV4LMJPEG      = (GtkCheckButton*) lookup_widget( GTK_WIDGET(button), "checkV4LMJPEG" );
699     b_v4l_mjpeg = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkV4LMJPEG));
700     if (b_v4l_mjpeg)
701     {
702         entryV4LDecimation = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LDecimation" );
703         i_v4l_decimation = gtk_spin_button_get_value_as_int(entryV4LDecimation);
704         pos += snprintf( &v4l_mrl[pos], VLC_MAX_MRL - pos, ":mjpeg:%d", (int)i_v4l_decimation );
705     }
706     /* end MJPEG only */
707
708     if (pos >= VLC_MAX_MRL)
709     {
710         v4l_mrl[VLC_MAX_MRL-1]='\0';
711         msg_Err(p_intf, "Media Resource Locator is truncated to: %s", v4l_mrl);
712     }
713
714     PlaylistAddItem(GTK_WIDGET(button), (gchar*) &v4l_mrl);
715 }
716
717
718 gboolean
719 PlaylistEvent                          (GtkWidget       *widget,
720                                         GdkEvent        *event,
721                                         gpointer         user_data)
722 {
723     return FALSE;
724 }
725
726
727 void
728 onPlaylistColumnsChanged               (GtkTreeView     *treeview,
729                                         gpointer         user_data)
730 {
731 }
732
733
734 gboolean
735 onPlaylistRowSelected                  (GtkTreeView     *treeview,
736                                         gboolean         start_editing,
737                                         gpointer         user_data)
738 {
739     return FALSE;
740 }
741
742
743 void
744 onPlaylistRow                          (GtkTreeView     *treeview,
745                                         GtkTreePath     *path,
746                                         GtkTreeViewColumn *column,
747                                         gpointer         user_data)
748 {
749 }
750
751
752 void
753 onUpdatePlaylist                       (GtkButton       *button,
754                                         gpointer         user_data)
755 {
756     intf_thread_t *  p_intf = GtkGetIntf( button );
757     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
758                                                        FIND_ANYWHERE );
759     GtkTreeView *p_tvplaylist = NULL;
760
761     if( p_playlist == NULL )
762     {
763         return;
764     }
765
766     p_tvplaylist = (GtkTreeView*) lookup_widget( GTK_WIDGET(button), "tvPlaylist");
767     if (p_tvplaylist)
768     {
769         GtkListStore *p_model = NULL;
770
771         /* Rebuild the playlist then. */
772         p_model = gtk_list_store_new (3,
773                     G_TYPE_STRING, /* Filename */
774                     G_TYPE_STRING, /* Time */
775                     G_TYPE_UINT);  /* Hidden field */
776         if (p_model)
777         {
778             PlaylistRebuildListStore(p_model, p_playlist);
779             gtk_tree_view_set_model(GTK_TREE_VIEW(p_tvplaylist), GTK_TREE_MODEL(p_model));
780             g_object_unref(p_model);
781         }
782     }
783     vlc_object_release( p_playlist );
784 }
785
786 void
787 onDeletePlaylist                       (GtkButton       *button,
788                                         gpointer         user_data)
789 {
790     intf_thread_t *p_intf = GtkGetIntf( button );
791     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
792                                                        FIND_ANYWHERE );
793     GtkTreeView    *p_tvplaylist;
794
795     /* Delete an arbitrary item from the playlist */
796     p_tvplaylist = (GtkTreeView *) lookup_widget( GTK_WIDGET(button), "tvPlaylist" );
797     if (p_tvplaylist != NULL)
798     {
799         GList *p_rows = NULL;
800         GList *p_node;
801         GtkTreeModel *p_model = NULL;
802         GtkTreeSelection *p_selection = gtk_tree_view_get_selection(p_tvplaylist);
803
804         p_model = gtk_tree_view_get_model(p_tvplaylist);
805         if (p_model)
806         {
807             p_rows = gtk_tree_selection_get_selected_rows(p_selection, &p_model);
808
809             if( g_list_length( p_rows ) )
810             {
811                 /* reverse-sort so that we can delete from the furthest
812                  * to the closest item to delete...
813                  */
814                 p_rows = g_list_reverse( p_rows );
815             }
816     
817             for (p_node=p_rows; p_node!=NULL; p_node = p_node->next)
818             {
819                 GtkTreeIter iter;
820                 GtkTreePath *p_path = NULL;
821
822                 p_path = (GtkTreePath *)p_node->data;
823                 if (p_path)
824                 {
825                     if (gtk_tree_model_get_iter(p_model, &iter, p_path))
826                     {
827                         gint item;
828
829                         gtk_tree_model_get(p_model, &iter, 2, &item, -1);
830                         playlist_Delete(p_playlist, item);
831                     }
832                 }
833             }
834             g_list_foreach (p_rows, gtk_tree_path_free, NULL);
835             g_list_free (p_rows);
836         }
837
838         /* Rebuild the playlist then. */
839         p_model = gtk_list_store_new (3,
840                     G_TYPE_STRING, /* Filename */
841                     G_TYPE_STRING, /* Time */
842                     G_TYPE_UINT);  /* Hidden field */
843         if (p_model)
844         {
845             PlaylistRebuildListStore(GTK_LIST_STORE(p_model), p_playlist);
846             gtk_tree_view_set_model(GTK_TREE_VIEW(p_tvplaylist), GTK_TREE_MODEL(p_model));
847             g_object_unref(p_model);
848         }
849     }
850     vlc_object_release( p_playlist );
851 }
852
853
854 void
855 onClearPlaylist                        (GtkButton       *button,
856                                         gpointer         user_data)
857 {
858     intf_thread_t *p_intf = GtkGetIntf( button );
859     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
860                                                        FIND_ANYWHERE );
861     GtkTreeView    *p_tvplaylist;
862     int item;
863
864     if( p_playlist == NULL )
865     {
866         return;
867     }
868
869     for(item = p_playlist->i_size - 1; item >= 0 ;item-- )
870     {
871         playlist_Delete( p_playlist, item);
872     }
873     vlc_object_release( p_playlist );
874
875     // Remove all entries from the Playlist widget.
876     p_tvplaylist = (GtkTreeView*) lookup_widget( GTK_WIDGET(button), "tvPlaylist");
877     if (p_tvplaylist)
878     {
879         GtkTreeModel *p_play_model;
880
881         p_play_model = gtk_tree_view_get_model(p_tvplaylist);
882         if (p_play_model)
883         {
884             gtk_list_store_clear(GTK_LIST_STORE(p_play_model));
885         }
886     }
887 }
888
889
890 void
891 onPreferenceSave                       (GtkButton       *button,
892                                         gpointer         user_data)
893 {
894 #if 0
895     intf_thread_t *p_intf = GtkGetIntf( button );
896
897     msg_Dbg(p_intf, "Preferences Save" );
898     config_SaveConfigFile( p_intf, NULL );
899 #endif
900 }
901
902
903 void
904 onPreferenceApply                      (GtkButton       *button,
905                                         gpointer         user_data)
906 {
907 #if 0
908     intf_thread_t *p_intf = GtkGetIntf( button );
909
910     msg_Dbg(p_intf, "Preferences Apply" );
911 #endif
912 }
913
914
915 void
916 onPreferenceCancel                     (GtkButton       *button,
917                                         gpointer         user_data)
918 {
919 #if 0
920     intf_thread_t *p_intf = GtkGetIntf( button );
921
922     msg_Dbg(p_intf, "Preferences Cancel" );
923     config_ResetAll( p_intf );
924     /* Cancel interface changes. */
925     config_SaveConfigFile( p_intf, NULL );
926 #endif
927 }
928
929
930 void
931 onAddTranscodeToPlaylist               (GtkButton       *button,
932                                         gpointer         user_data)
933 {
934     intf_thread_t *p_intf = GtkGetIntf( button );
935
936     GtkEntry       *entryVideoCodec = NULL;
937     GtkSpinButton  *entryVideoBitrate = NULL;
938     GtkSpinButton  *entryVideoBitrateTolerance = NULL;
939     GtkSpinButton  *entryVideoKeyFrameInterval = NULL;
940     GtkCheckButton *checkVideoDeinterlace = NULL;
941     GtkEntry       *entryAudioCodec = NULL;
942     GtkSpinButton  *entryAudioBitrate = NULL;
943     const gchar    *p_video_codec;
944     gint            i_video_bitrate;
945     gint            i_video_bitrate_tolerance;
946     gint            i_video_keyframe_interval;
947     gboolean        b_video_deinterlace;
948     const gchar    *p_audio_codec;
949     gint            i_audio_bitrate;
950
951     GtkEntry       *entryStdAccess = NULL;
952     GtkEntry       *entryStdMuxer = NULL;
953     GtkEntry       *entryStdURL = NULL;
954     GtkSpinButton  *entryStdTTL = NULL;
955     const gchar    *p_std_access;
956     const gchar    *p_std_muxer;
957     const gchar    *p_std_url;
958     gint            i_std_ttl;
959
960     gchar mrl[VLC_MAX_MRL];
961     int   pos;
962
963     pos = snprintf( &mrl[0], VLC_MAX_MRL, "--sout '#transcode{");
964
965     entryVideoCodec   = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryVideoCodec" );
966     entryVideoBitrate = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryVideoBitrate" );
967     entryVideoBitrateTolerance = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryVideoBitrateTolerance" );
968     entryVideoKeyFrameInterval = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryVideoKeyFrameInterval" );
969     
970     p_video_codec = gtk_entry_get_text(GTK_ENTRY(entryVideoCodec));
971     i_video_bitrate = gtk_spin_button_get_value_as_int(entryVideoBitrate);
972     i_video_bitrate_tolerance = gtk_spin_button_get_value_as_int(entryVideoBitrateTolerance);
973     i_video_keyframe_interval = gtk_spin_button_get_value_as_int(entryVideoKeyFrameInterval);
974     
975     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "vcodec=%s,", (char*)p_video_codec );
976     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "vb=%d,", (int)i_video_bitrate );
977     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "vt=%d,", (int)i_video_bitrate_tolerance );
978     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "keyint=%d,", (int)i_video_keyframe_interval );
979
980     checkVideoDeinterlace = (GtkCheckButton*) lookup_widget( GTK_WIDGET(button), "checkVideoDeinterlace" );
981     b_video_deinterlace = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkVideoDeinterlace));
982     if (b_video_deinterlace)
983     {
984         pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "deinterlace," );
985     }
986     entryAudioCodec   = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryAudioCodec" );
987     entryAudioBitrate = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryAudioBitrate" );
988
989     p_audio_codec = gtk_entry_get_text(GTK_ENTRY(entryAudioCodec));
990     i_audio_bitrate = gtk_spin_button_get_value_as_int(entryAudioBitrate);
991
992     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "acodec=%s,", (char*)p_audio_codec );
993     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "ab=%d", (int)i_audio_bitrate );
994
995     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "}:std{" );
996
997     entryStdAccess = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryStdAccess" );
998     entryStdMuxer  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryStdMuxer" );
999     entryStdURL = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryStdURL" );
1000     entryStdTTL = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryStdTTL" );
1001
1002     p_std_access = gtk_entry_get_text(GTK_ENTRY(entryStdAccess));
1003     p_std_muxer = gtk_entry_get_text(GTK_ENTRY(entryStdMuxer));
1004     p_std_url = gtk_entry_get_text(GTK_ENTRY(entryStdURL));
1005
1006     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "access=%s,", (char*)p_std_access);
1007     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "mux=%s,", (char*)p_std_muxer);
1008     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "url=%s", (char*)p_std_url);
1009     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, "}'");
1010
1011     i_std_ttl = gtk_spin_button_get_value_as_int(entryStdTTL);
1012
1013     pos += snprintf( &mrl[pos], VLC_MAX_MRL - pos, " --ttl=%d", (int)i_std_ttl);
1014
1015     if (pos >= VLC_MAX_MRL)
1016     {
1017         mrl[VLC_MAX_MRL-1]='\0';
1018         msg_Err(p_intf, "Media Resource Locator is truncated to: %s", mrl );
1019     }
1020
1021     PlaylistAddItem(GTK_WIDGET(button), (gchar*) &mrl);
1022 }
1023
1024