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