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