]> git.sesse.net Git - vlc/blob - modules/gui/pda/pda_callbacks.c
Remove _GNU_SOURCE and string.h too
[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 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <sys/types.h>                                              /* off_t */
28 #include <vlc/vlc.h>
29 #include <vlc_interface.h>
30 #include <vlc_playlist.h>
31 #include <vlc_vout.h>
32
33 #include <stdio.h>
34 #include <dirent.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <pwd.h>
38 #include <grp.h>
39
40 #ifdef HAVE_CONFIG_H
41 #  include <config.h>
42 #endif
43
44 #include <gtk/gtk.h>
45
46 #include "pda_callbacks.h"
47 #include "pda_interface.h"
48 #include "pda_support.h"
49 #include "pda.h"
50
51 #define VLC_MAX_MRL     256
52
53 static char *get_file_perms(struct stat st);
54
55 /*****************************************************************************
56  * Useful function to retrieve p_intf
57  ****************************************************************************/
58 void * E_(__GtkGetIntf)( GtkWidget * widget )
59 {
60     void *p_data;
61
62     if( GTK_IS_MENU_ITEM( widget ) )
63     {
64         /* Look for a GTK_MENU */
65         while( widget->parent && !GTK_IS_MENU( widget ) )
66         {
67             widget = widget->parent;
68         }
69
70         /* Maybe this one has the data */
71         p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
72         if( p_data )
73         {
74             return p_data;
75         }
76
77         /* Otherwise, the parent widget has it */
78         widget = gtk_menu_get_attach_widget( GTK_MENU( widget ) );
79     }
80
81     /* We look for the top widget */
82     widget = gtk_widget_get_toplevel( GTK_WIDGET( widget ) );
83
84     p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
85
86     return p_data;
87 }
88
89 void PlaylistAddItem(GtkWidget *widget, gchar *name, char **ppsz_options, int i_size)
90 {
91     intf_thread_t *p_intf = GtkGetIntf( widget );
92     playlist_t    *p_playlist;
93     int           i_id , i_pos=0;
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                 i_id = playlist_AddExt( p_playlist, (const char*)name,
136                               (const char*)name,
137                               PLAYLIST_APPEND, PLAYLIST_END,
138                               (mtime_t) 0,
139                               (const char **) ppsz_options, i_pos );
140             }
141
142             /* Cleanup memory */
143             for (i=0; i<i_size; i++)
144                 free(ppsz_options[i]);
145             free(ppsz_options);
146         }
147     }
148     vlc_object_release( p_playlist );
149 }
150
151 void PlaylistRebuildListStore( GtkListStore * p_list, playlist_t * p_playlist )
152 {
153     GtkTreeIter iter;
154     int         i_dummy;
155     gchar *     ppsz_text[2];
156 #if 0
157     GdkColor    red;
158     red.red     = 65535;
159     red.blue    = 0;
160     red.green   = 0;
161 #endif
162     vlc_mutex_lock( &p_playlist->object_lock );
163     for( i_dummy = 0; i_dummy < p_playlist->i_size ; i_dummy++ )
164     {
165         ppsz_text[0] = p_playlist->pp_items[i_dummy]->input.psz_name;
166         ppsz_text[1] = "no info";
167         gtk_list_store_append (p_list, &iter);
168         gtk_list_store_set (p_list, &iter,
169                             0, ppsz_text[0],
170                             1, ppsz_text[1],
171                             2, i_dummy, /* Hidden index */
172                             -1);
173     }
174     vlc_mutex_unlock( &p_playlist->object_lock );
175 }
176
177 /*****************************************************************
178  * Read directory helper function.
179  ****************************************************************/
180 void ReadDirectory(intf_thread_t *p_intf, GtkListStore *p_list, char *psz_dir )
181 {
182     GtkTreeIter    iter;
183     struct dirent **pp_namelist;
184     struct passwd *p_pw;
185     struct group  *p_grp;
186     struct stat    st;
187     int n=-1, status=-1;
188
189     msg_Dbg(p_intf, "Changing to dir %s", psz_dir);
190     if (psz_dir)
191     {
192        status = chdir(psz_dir);
193        if (status<0)
194           msg_Dbg(p_intf, "permision denied" );
195     }
196     n = scandir(".", &pp_namelist, 0, alphasort);
197
198     if (n<0)
199         perror("scandir");
200     else
201     {
202         int i;
203         gchar *ppsz_text[4];
204
205         if (lstat("..", &st)==0)
206         {
207             /* user, group  */
208             p_pw  = getpwuid(st.st_uid);
209             p_grp = getgrgid(st.st_gid);
210
211             /* XXX : kludge temporaire pour yopy */
212             ppsz_text[0] = "..";
213             ppsz_text[1] = get_file_perms(st);
214             ppsz_text[2] = p_pw->pw_name;
215             ppsz_text[3] = p_grp->gr_name;
216
217             /* Add a new row to the model */
218             gtk_list_store_append (p_list, &iter);
219             gtk_list_store_set (p_list, &iter,
220                                 0, ppsz_text[0],
221                                 1, ppsz_text[1],
222                                 2, st.st_size,
223                                 3, ppsz_text[2],
224                                 4, ppsz_text[3],
225                                 -1);
226
227             if (ppsz_text[1]) free(ppsz_text[1]);
228         }
229             /* kludge */
230         for (i=0; i<n; i++)
231         {           
232             if ((pp_namelist[i]->d_name[0] != '.') &&
233                 (lstat(pp_namelist[i]->d_name, &st)==0))
234             {
235                 /* user, group  */
236                 p_pw  = getpwuid(st.st_uid);
237                 p_grp = getgrgid(st.st_gid);
238
239                 /* This is a list of strings. */
240                 ppsz_text[0] = pp_namelist[i]->d_name;
241                 ppsz_text[1] = get_file_perms(st);
242                 ppsz_text[2] = p_pw->pw_name;
243                 ppsz_text[3] = p_grp->gr_name;
244 #if 0
245                 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] );
246 #endif
247                 gtk_list_store_append (p_list, &iter);
248                 gtk_list_store_set (p_list, &iter,
249                                     0, ppsz_text[0],
250                                     1, ppsz_text[1],
251                                     2, st.st_size,
252                                     3, ppsz_text[2],
253                                     4, ppsz_text[3],
254                                     -1);
255
256                 if (ppsz_text[1]) free(ppsz_text[1]);
257             }
258         }
259         free(pp_namelist);
260     }
261 }
262
263 static char *get_file_perms(const struct stat st)
264 {
265     char  *psz_perm;
266
267     psz_perm = (char *) malloc(sizeof(char)*10);
268     strncpy( psz_perm, "----------", sizeof("----------"));
269
270     /* determine permission modes */
271     if (S_ISLNK(st.st_mode))
272         psz_perm[0]= 'l';
273     else if (S_ISDIR(st.st_mode))
274         psz_perm[0]= 'd';
275     else if (S_ISCHR(st.st_mode))
276         psz_perm[0]= 'c';
277     else if (S_ISBLK(st.st_mode))
278         psz_perm[0]= 'b';
279     else if (S_ISFIFO(st.st_mode))
280         psz_perm[0]= 'f';
281     else if (S_ISSOCK(st.st_mode))
282         psz_perm[0]= 's';
283     else if (S_ISREG(st.st_mode))
284         psz_perm[0]= '-';
285     else /* Unknown type is an error */
286         psz_perm[0]= '?';
287     /* Get file permissions */
288     /* User */
289     if (st.st_mode & S_IRUSR)
290         psz_perm[1]= 'r';
291     if (st.st_mode & S_IWUSR)
292         psz_perm[2]= 'w';
293     if (st.st_mode & S_IXUSR)
294     {
295         if (st.st_mode & S_ISUID)
296             psz_perm[3] = 's';
297         else
298             psz_perm[3]= 'x';
299     }
300     else if (st.st_mode & S_ISUID)
301         psz_perm[3] = 'S';
302     /* Group */
303     if (st.st_mode & S_IRGRP)
304         psz_perm[4]= 'r';
305     if (st.st_mode & S_IWGRP)
306         psz_perm[5]= 'w';
307     if (st.st_mode & S_IXGRP)
308     {
309         if (st.st_mode & S_ISGID)
310             psz_perm[6] = 's';
311         else
312             psz_perm[6]= 'x';
313     }
314     else if (st.st_mode & S_ISGID)
315         psz_perm[6] = 'S';
316     /* Other */
317     if (st.st_mode & S_IROTH)
318         psz_perm[7]= 'r';
319     if (st.st_mode & S_IWOTH)
320         psz_perm[8]= 'w';
321     if (st.st_mode & S_IXOTH)
322     {
323         /* 'sticky' bit */
324         if (st.st_mode &S_ISVTX)
325             psz_perm[9] = 't';
326         else
327             psz_perm[9]= 'x';
328     }
329     else if (st.st_mode &S_ISVTX)
330         psz_perm[9]= 'T';
331
332     return psz_perm;
333 }
334
335 /*
336  * Main interface callbacks
337  */
338
339 gboolean onPDADeleteEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
340 {
341     intf_thread_t *p_intf = GtkGetIntf( widget );
342
343     vlc_mutex_lock( &p_intf->change_lock );
344     vlc_object_kill( p_intf->p_libvlc );
345     vlc_mutex_unlock( &p_intf->change_lock );
346     msg_Dbg( p_intf, "about to exit vlc ... signaled" );
347
348     return TRUE;
349 }
350
351 void onRewind(GtkButton *button, gpointer user_data)
352 {
353     intf_thread_t *p_intf = GtkGetIntf( button );
354
355     if (p_intf->p_sys->p_input != NULL)
356     {
357         var_SetVoid( p_intf->p_sys->p_input, "rate-slower" );
358     }
359 }
360
361 void onPause(GtkButton *button, gpointer user_data)
362 {
363     intf_thread_t *p_intf = GtkGetIntf( button );
364
365     if (p_intf->p_sys->p_input != NULL)
366     {
367         var_SetInteger( p_intf->p_sys->p_input, "state", PAUSE_S );
368     }
369 }
370
371
372 void onPlay(GtkButton *button, 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             gdk_window_lower( p_intf->p_sys->p_window->window );
385         }
386         else
387         {
388             vlc_mutex_unlock( &p_playlist->object_lock );
389         }
390         vlc_object_release( p_playlist );
391     }
392 }
393
394 void onStop(GtkButton *button, gpointer user_data)
395 {
396     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET( button ) );
397     playlist_t *p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
398                                                        FIND_ANYWHERE );
399     if (p_playlist)
400     {
401         playlist_Stop( p_playlist );
402         vlc_object_release( p_playlist );
403         gdk_window_raise( p_intf->p_sys->p_window->window );
404     }
405 }
406
407 void onForward(GtkButton *button, gpointer user_data)
408 {
409     intf_thread_t *p_intf = GtkGetIntf( button );
410
411     if (p_intf->p_sys->p_input != NULL)
412     {
413         var_SetVoid( p_intf->p_sys->p_input, "rate-faster" );
414     }
415 }
416
417
418 void onAbout(GtkButton *button, gpointer user_data)
419 {
420     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(button) );
421
422     /* Toggle notebook */
423     if (p_intf->p_sys->p_notebook)
424     {
425         gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
426         gtk_notebook_set_page(p_intf->p_sys->p_notebook,6);
427     }
428 }
429
430 gboolean SliderRelease(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
431 {
432     intf_thread_t *p_intf = GtkGetIntf( widget );
433
434     msg_Dbg( p_intf, "SliderButton Release" );
435     vlc_mutex_lock( &p_intf->change_lock );
436     p_intf->p_sys->b_slider_free = 1;
437     vlc_mutex_unlock( &p_intf->change_lock );
438
439     return TRUE;
440 }
441
442 gboolean SliderPress(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
443 {
444     intf_thread_t *p_intf = GtkGetIntf( widget );
445
446     msg_Dbg( p_intf, "SliderButton Press" );
447     vlc_mutex_lock( &p_intf->change_lock );
448     p_intf->p_sys->b_slider_free = 0;
449     vlc_mutex_unlock( &p_intf->change_lock );
450
451     return FALSE;
452 }
453
454 void SliderMove(GtkRange *range, GtkScrollType scroll, gpointer user_data)
455 {
456     intf_thread_t *p_intf = GtkGetIntf( range );
457     msg_Dbg( p_intf, "SliderButton Move" );
458 }
459
460
461 void addSelectedToPlaylist(GtkTreeModel *model, GtkTreePath *path,
462                            GtkTreeIter *iter, gpointer *userdata)
463 {
464     gchar *psz_filename;
465
466     gtk_tree_model_get(model, iter, 0, &psz_filename, -1);
467
468     PlaylistAddItem(GTK_WIDGET(userdata), psz_filename, 0, 0);
469 }
470
471 void onFileListRow(GtkTreeView *treeview, GtkTreePath *path,
472                    GtkTreeViewColumn *column, gpointer user_data)
473 {
474     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(treeview) );
475     GtkTreeSelection *p_selection = gtk_tree_view_get_selection(treeview);
476
477     if (gtk_tree_selection_count_selected_rows(p_selection) == 1)
478     {
479         struct stat   st;
480         GtkTreeModel *p_model;
481         GtkTreeIter   iter;
482         gchar        *psz_filename;
483
484         /* This might be a directory selection */
485         p_model = gtk_tree_view_get_model(treeview);
486         if (!p_model)
487         {
488             msg_Err(p_intf, "PDA: Filelist model contains a NULL pointer\n" );
489             return;
490         }
491         if (!gtk_tree_model_get_iter(p_model, &iter, path))
492         {
493             msg_Err( p_intf, "PDA: Could not get iter from model" );
494             return;
495         }
496
497         gtk_tree_model_get(p_model, &iter, 0, &psz_filename, -1);
498         if (stat((char*)psz_filename, &st)==0)
499         {
500             if (S_ISDIR(st.st_mode))
501             {
502                 GtkListStore *p_store = NULL;
503
504                 /* Get new directory listing */
505                 p_store = gtk_list_store_new (5,
506                                            G_TYPE_STRING,
507                                            G_TYPE_STRING,
508                                            G_TYPE_UINT64,
509                                            G_TYPE_STRING,
510                                            G_TYPE_STRING);
511                 if (p_store)
512                 {
513                     ReadDirectory(p_intf, p_store, psz_filename);
514
515                     /* Update TreeView with new model */
516                     gtk_tree_view_set_model(treeview, (GtkTreeModel*) p_store);
517                     g_object_unref(p_store);
518                 }
519             }
520         }
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 *p_networkPort = NULL;
542     GtkEntry      *p_entryMRL = NULL;
543     GtkEntry      *p_networkType = NULL;
544     GtkEntry      *p_networkAddress = NULL;
545     GtkEntry      *p_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     p_entryMRL = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryMRL" );
554
555     p_networkType     = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryNetworkType" );
556     p_networkAddress  = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryNetworkAddress" );
557     p_networkPort     = (GtkSpinButton*) lookup_widget( GTK_WIDGET(editable), "entryNetworkPort" );
558     p_networkProtocol = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryNetworkProtocolType" );
559
560     psz_mrlNetworkType = gtk_entry_get_text(GTK_ENTRY(p_networkType));
561     psz_mrlAddress     = gtk_entry_get_text(GTK_ENTRY(p_networkAddress));
562     i_mrlPort          = gtk_spin_button_get_value_as_int(p_networkPort);
563     psz_mrlProtocol    = gtk_entry_get_text(GTK_ENTRY(p_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(p_entryMRL,text);
580 }
581
582 void onAddNetworkPlaylist(GtkButton *button, gpointer user_data)
583 {
584     intf_thread_t  *p_intf = GtkGetIntf( button );
585
586     GtkEntry       *p_mrl = NULL;
587     GtkCheckButton *p_network_transcode = NULL;
588     gboolean        b_network_transcode;
589     const gchar    *psz_mrl_name;
590
591     p_mrl = (GtkEntry*) lookup_widget(GTK_WIDGET(button),"entryMRL" );
592     psz_mrl_name = gtk_entry_get_text(p_mrl);
593
594     p_network_transcode = (GtkCheckButton*) lookup_widget(GTK_WIDGET(button), "checkNetworkTranscode" );
595     b_network_transcode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_network_transcode));
596     if (b_network_transcode)
597     {
598         msg_Dbg( p_intf, "Network transcode option selected." );
599         onAddTranscodeToPlaylist(GTK_WIDGET(button), (gchar *)psz_mrl_name);
600     }
601     else
602     {
603         msg_Dbg( p_intf, "Network receiving selected." );
604         PlaylistAddItem(GTK_WIDGET(button), (gchar *)psz_mrl_name, 0, 0);
605     }
606 }
607
608
609 void onAddCameraToPlaylist(GtkButton *button, gpointer user_data)
610 {
611     intf_thread_t *p_intf = GtkGetIntf( button );
612
613     GtkSpinButton *entryV4LChannel = NULL;
614     GtkSpinButton *entryV4LFrequency = NULL;
615     GtkSpinButton *entryV4LSampleRate = NULL;
616     GtkSpinButton *entryV4LQuality = NULL;
617     GtkSpinButton *entryV4LTuner = NULL;
618     gint    i_v4l_channel;
619     gint    i_v4l_frequency;
620     gint    i_v4l_samplerate;
621     gint    i_v4l_quality;
622     gint    i_v4l_tuner;
623
624     GtkEntry      *entryV4LVideoDevice = NULL;
625     GtkEntry      *entryV4LAudioDevice = NULL;
626     GtkEntry      *entryV4LNorm = NULL;
627     GtkEntry      *entryV4LSize = NULL;
628     GtkEntry      *entryV4LSoundDirection = NULL;
629     const gchar   *p_v4l_video_device;
630     const gchar   *p_v4l_audio_device;
631     const gchar   *p_v4l_norm;
632     const gchar   *p_v4l_size;
633     const gchar   *p_v4l_sound_direction;
634
635     /* MJPEG only */
636     GtkCheckButton *checkV4LMJPEG = NULL;
637     GtkSpinButton  *entryV4LDecimation = NULL;
638     gboolean        b_v4l_mjpeg;
639     gint            i_v4l_decimation;
640     /* end MJPEG only */
641
642     GtkCheckButton  *p_check_v4l_transcode = NULL;
643     gboolean         b_v4l_transcode;
644     
645     char **ppsz_options = NULL; /* list of options */
646     int  i_options=0;
647     char v4l_mrl[6];
648     int i_pos;
649     int i;
650
651     ppsz_options = (char **) malloc(11 *sizeof(char*));
652     if (ppsz_options == NULL)
653     {
654         msg_Err(p_intf, "No memory to allocate for v4l options.");
655         return;
656     }
657     for (i=0; i<11; i++)
658     {
659         ppsz_options[i] = (char *) malloc(VLC_MAX_MRL * sizeof(char));
660         if (ppsz_options[i] == NULL)
661         {
662             msg_Err(p_intf, "No memory to allocate for v4l options string %i.", i);
663             for (i-=1; i>=0; i--)
664                 free(ppsz_options[i]);
665             free(ppsz_options);
666             return;
667         }
668     }
669
670     i_pos = snprintf( &v4l_mrl[0], 6, "v4l");
671     v4l_mrl[5]='\0';
672
673     entryV4LChannel    = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LChannel" );
674     entryV4LFrequency  = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LFrequency" );
675     entryV4LSampleRate = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LSampleRate" );
676     entryV4LQuality    = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LQuality" );
677     entryV4LTuner      = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LTuner" );
678
679     entryV4LVideoDevice  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LVideoDevice" );
680     entryV4LAudioDevice  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LAudioDevice" );
681     entryV4LNorm  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LNorm" );
682     entryV4LSize  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LSize" );
683     entryV4LSoundDirection  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryV4LSoundDirection" );
684
685     i_v4l_channel = gtk_spin_button_get_value_as_int(entryV4LChannel);
686     i_v4l_frequency = gtk_spin_button_get_value_as_int(entryV4LFrequency);
687     i_v4l_samplerate = gtk_spin_button_get_value_as_int(entryV4LSampleRate);
688     i_v4l_quality = gtk_spin_button_get_value_as_int(entryV4LQuality);
689     i_v4l_tuner = gtk_spin_button_get_value_as_int(entryV4LTuner);
690
691     p_v4l_video_device = gtk_entry_get_text(GTK_ENTRY(entryV4LVideoDevice));
692     p_v4l_audio_device = gtk_entry_get_text(GTK_ENTRY(entryV4LAudioDevice));
693     p_v4l_norm = gtk_entry_get_text(GTK_ENTRY(entryV4LNorm));
694     p_v4l_size  = gtk_entry_get_text(GTK_ENTRY(entryV4LSize));
695     p_v4l_sound_direction = gtk_entry_get_text(GTK_ENTRY(entryV4LSoundDirection));
696
697     i_pos = snprintf( &ppsz_options[i_options++][0], VLC_MAX_MRL, "%s", (char*)p_v4l_video_device );
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, "adev=%s", (char*)p_v4l_audio_device );
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, "norm=%s", (char*)p_v4l_norm );
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, "size=%s", (char*)p_v4l_size );
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, "%s", (char*)p_v4l_sound_direction );
706     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
707
708     i_pos = snprintf( &ppsz_options[i_options++][0], VLC_MAX_MRL, "channel=%d", (int)i_v4l_channel );
709     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
710     i_pos = snprintf( &ppsz_options[i_options++][0], VLC_MAX_MRL, "frequency=%d", (int)i_v4l_frequency );
711     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
712     i_pos = snprintf( &ppsz_options[i_options++][0], VLC_MAX_MRL, "samplerate=%d", (int)i_v4l_samplerate );
713     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
714     i_pos = snprintf( &ppsz_options[i_options++][0], VLC_MAX_MRL, "quality=%d", (int)i_v4l_quality );
715     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
716     i_pos = snprintf( &ppsz_options[i_options++][0], VLC_MAX_MRL, "tuner=%d", (int)i_v4l_tuner );
717     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
718
719     /* MJPEG only */
720     checkV4LMJPEG      = (GtkCheckButton*) lookup_widget( GTK_WIDGET(button), "checkV4LMJPEG" );
721     b_v4l_mjpeg = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkV4LMJPEG));
722     if (b_v4l_mjpeg)
723     {
724         entryV4LDecimation = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryV4LDecimation" );
725         i_v4l_decimation = gtk_spin_button_get_value_as_int(entryV4LDecimation);
726
727         i_pos = snprintf( &ppsz_options[i_options++][0], VLC_MAX_MRL, "mjpeg:%d", (int)i_v4l_decimation );
728         if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
729     }
730     /* end MJPEG only */
731
732     p_check_v4l_transcode = (GtkCheckButton*) lookup_widget(GTK_WIDGET(button), "checkV4LTranscode" );
733     b_v4l_transcode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_check_v4l_transcode));
734     if (b_v4l_transcode)
735     {
736         msg_Dbg( p_intf, "Camera transcode option selected." );
737         onAddTranscodeToPlaylist(GTK_WIDGET(button), (gchar *)v4l_mrl);
738     }
739     else
740     {
741         msg_Dbg( p_intf, "Camera reception option selected." );
742         PlaylistAddItem(GTK_WIDGET(button), (gchar*) &v4l_mrl, ppsz_options, i_options);
743     }
744 }
745
746
747 gboolean PlaylistEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
748 {
749     return FALSE;
750 }
751
752
753 void onPlaylistColumnsChanged(GtkTreeView *treeview, gpointer user_data)
754 {
755 }
756
757
758 gboolean onPlaylistRowSelected(GtkTreeView *treeview, gboolean start_editing, gpointer user_data)
759 {
760     return FALSE;
761 }
762
763
764 void onPlaylistRow(GtkTreeView *treeview, GtkTreePath *path,
765                    GtkTreeViewColumn *column, gpointer user_data)
766 {
767     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(treeview) );
768     GtkTreeSelection *p_selection = gtk_tree_view_get_selection(treeview);
769     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
770                                                        FIND_ANYWHERE );
771
772     if( p_playlist == NULL )
773     {
774         return; // FALSE;
775     }
776
777     if (gtk_tree_selection_count_selected_rows(p_selection) == 1)
778     {
779         GtkTreeModel *p_model;
780         GtkTreeIter   iter;
781         int           i_row;
782
783         /* This might be a directory selection */
784         p_model = gtk_tree_view_get_model(treeview);
785         if (!p_model)
786         {
787             msg_Err(p_intf, "PDA: Playlist model contains a NULL pointer\n" );
788             return;
789         }
790         if (!gtk_tree_model_get_iter(p_model, &iter, path))
791         {
792             msg_Err( p_intf, "PDA: Playlist could not get iter from model" );
793             return;
794         }
795
796         gtk_tree_model_get(p_model, &iter, 2, &i_row, -1);
797         playlist_Goto( p_playlist, i_row );
798     }
799     vlc_object_release( p_playlist );
800 }
801
802
803 void onUpdatePlaylist(GtkButton *button, gpointer user_data)
804 {
805     intf_thread_t *  p_intf = GtkGetIntf( button );
806     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
807                                                        FIND_ANYWHERE );
808     GtkTreeView *p_tvplaylist = NULL;
809
810     if( p_playlist == NULL )
811     {
812         return;
813     }
814
815     p_tvplaylist = (GtkTreeView*) lookup_widget( GTK_WIDGET(button), "tvPlaylist");
816     if (p_tvplaylist)
817     {
818         GtkListStore *p_model = NULL;
819
820         /* Rebuild the playlist then. */
821         p_model = gtk_list_store_new (3,
822                     G_TYPE_STRING, /* Filename */
823                     G_TYPE_STRING, /* Time */
824                     G_TYPE_UINT);  /* Hidden field */
825         if (p_model)
826         {
827             PlaylistRebuildListStore(p_model, p_playlist);
828             gtk_tree_view_set_model(GTK_TREE_VIEW(p_tvplaylist), GTK_TREE_MODEL(p_model));
829             g_object_unref(p_model);
830         }
831     }
832     vlc_object_release( p_playlist );
833 }
834
835 void deleteItemFromPlaylist(gpointer data, gpointer user_data)
836 {
837     gtk_tree_path_free((GtkTreePath*) data); // removing an item.
838 }
839
840 void onDeletePlaylist(GtkButton *button, gpointer user_data)
841 {
842     intf_thread_t *p_intf = GtkGetIntf( button );
843     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
844                                                        FIND_ANYWHERE );
845     GtkTreeView    *p_tvplaylist;
846
847     /* Delete an arbitrary item from the playlist */
848     p_tvplaylist = (GtkTreeView *) lookup_widget( GTK_WIDGET(button), "tvPlaylist" );
849     if (p_tvplaylist != NULL)
850     {
851         GList *p_rows = NULL;
852         GList *p_node;
853         GtkTreeModel *p_model = NULL;
854         GtkListStore *p_store = NULL;
855         GtkTreeSelection *p_selection = gtk_tree_view_get_selection(p_tvplaylist);
856
857         p_model = gtk_tree_view_get_model(p_tvplaylist);
858         if (p_model)
859         {
860             p_rows = gtk_tree_selection_get_selected_rows(p_selection, &p_model);
861
862             if( g_list_length( p_rows ) )
863             {
864                 /* reverse-sort so that we can delete from the furthest
865                  * to the closest item to delete...
866                  */
867                 p_rows = g_list_reverse( p_rows );
868             }
869
870             for (p_node=p_rows; p_node!=NULL; p_node = p_node->next)
871             {
872                 GtkTreeIter iter;
873                 GtkTreePath *p_path = NULL;
874
875                 p_path = (GtkTreePath *)p_node->data;
876                 if (p_path)
877                 {
878                     if (gtk_tree_model_get_iter(p_model, &iter, p_path))
879                     {
880                         gint item;
881
882                         gtk_tree_model_get(p_model, &iter, 2, &item, -1);
883                         msg_Err( p_playlist, "PDA delete broken");
884                     }
885                 }
886             }
887 #if 0 
888             g_list_foreach (p_rows, (GFunc*)gtk_tree_path_free, NULL);
889 #endif /* Testing the next line */
890             g_list_foreach (p_rows, deleteItemFromPlaylist, NULL);
891             g_list_free (p_rows);
892         }
893
894         /* Rebuild the playlist then. */
895         p_store = gtk_list_store_new (3,
896                     G_TYPE_STRING, /* Filename */
897                     G_TYPE_STRING, /* Time */
898                     G_TYPE_UINT);  /* Hidden field */
899         if (p_store)
900         {
901             PlaylistRebuildListStore(p_store, p_playlist);
902             gtk_tree_view_set_model(GTK_TREE_VIEW(p_tvplaylist), GTK_TREE_MODEL(p_store));
903             g_object_unref(p_store);
904         }
905     }
906     vlc_object_release( p_playlist );
907 }
908
909
910 void onClearPlaylist(GtkButton *button, gpointer user_data)
911 {
912     intf_thread_t *p_intf = GtkGetIntf( button );
913     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
914                                                        FIND_ANYWHERE );
915     GtkTreeView    *p_tvplaylist;
916     int item;
917
918     if( p_playlist == NULL )
919     {
920         return;
921     }
922
923     for(item = p_playlist->i_size - 1; item >= 0 ;item-- )
924     {
925         msg_Err( p_playlist "fix pda delete");
926     }
927     vlc_object_release( p_playlist );
928
929     // Remove all entries from the Playlist widget.
930     p_tvplaylist = (GtkTreeView*) lookup_widget( GTK_WIDGET(button), "tvPlaylist");
931     if (p_tvplaylist)
932     {
933         GtkTreeModel *p_play_model;
934
935         p_play_model = gtk_tree_view_get_model(p_tvplaylist);
936         if (p_play_model)
937         {
938             gtk_list_store_clear(GTK_LIST_STORE(p_play_model));
939         }
940     }
941 }
942
943
944 void onPreferenceSave(GtkButton *button, gpointer user_data)
945 {
946 #if 0
947     intf_thread_t *p_intf = GtkGetIntf( button );
948
949     msg_Dbg(p_intf, "Preferences Save" );
950     config_SaveConfigFile( p_intf, NULL );
951 #endif
952 }
953
954
955 void onPreferenceApply(GtkButton *button, gpointer user_data)
956 {
957 #if 0
958     intf_thread_t *p_intf = GtkGetIntf( button );
959
960     msg_Dbg(p_intf, "Preferences Apply" );
961 #endif
962 }
963
964
965 void onPreferenceCancel(GtkButton *button, gpointer user_data)
966 {
967 #if 0
968     intf_thread_t *p_intf = GtkGetIntf( button );
969
970     msg_Dbg(p_intf, "Preferences Cancel" );
971     config_ResetAll( p_intf );
972     /* Cancel interface changes. */
973     config_SaveConfigFile( p_intf, NULL );
974 #endif
975 }
976
977
978 void onAddTranscodeToPlaylist(GtkButton *button, gpointer user_data)
979 {
980     intf_thread_t *p_intf = GtkGetIntf( button );
981
982     GtkEntry       *p_entryVideoCodec = NULL;
983     GtkSpinButton  *p_entryVideoBitrate = NULL;
984     GtkSpinButton  *p_entryVideoBitrateTolerance = NULL;
985     GtkSpinButton  *p_entryVideoKeyFrameInterval = NULL;
986     GtkCheckButton *p_checkVideoDeinterlace = NULL;
987     GtkEntry       *p_entryAudioCodec = NULL;
988     GtkSpinButton  *p_entryAudioBitrate = NULL;
989     const gchar    *p_video_codec;
990     gint            i_video_bitrate;
991     gint            i_video_bitrate_tolerance;
992     gint            i_video_keyframe_interval;
993     gboolean        b_video_deinterlace;
994     const gchar    *p_audio_codec;
995     gint            i_audio_bitrate;
996
997     GtkEntry       *p_entryStdAccess = NULL;
998     GtkEntry       *p_entryStdMuxer = NULL;
999     GtkEntry       *p_entryStdURL = NULL;
1000     GtkEntry       *p_entryStdAnnounce = NULL;
1001     GtkSpinButton  *p_entryStdTTL = NULL;
1002     GtkCheckButton *p_checkSAP = NULL;
1003     GtkCheckButton *p_checkSLP = NULL;
1004     const gchar    *p_std_announce;
1005     const gchar    *p_std_access;
1006     const gchar    *p_std_muxer;
1007     const gchar    *p_std_url;
1008     gboolean        b_sap_announce;
1009     gboolean        b_slp_announce;
1010     gint            i_std_ttl;
1011
1012     char **ppsz_options = NULL; /* list of options */
1013     int  i_options=0;
1014     int  i;
1015
1016     gchar mrl[7];
1017     int   i_pos;
1018
1019     ppsz_options = (char **) malloc(3 *sizeof(char*));
1020     if (ppsz_options == NULL)
1021     {
1022         msg_Err(p_intf, "No memory to allocate for v4l options.");
1023         return;
1024     }
1025     for (i=0; i<3; i++)
1026     {
1027         ppsz_options[i] = (char *) malloc(VLC_MAX_MRL * sizeof(char));
1028         if (ppsz_options[i] == NULL)
1029         {
1030             msg_Err(p_intf, "No memory to allocate for v4l options string %i.", i);
1031             for (i-=1; i>=0; i--)
1032                 free(ppsz_options[i]);
1033             free(ppsz_options);
1034             return;
1035         }
1036     }
1037
1038     /* Update the playlist */
1039     playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1040     if( p_playlist == NULL ) return;
1041
1042     /* Get all the options. */
1043     i_pos = snprintf( &mrl[0], VLC_MAX_MRL, "sout");
1044     mrl[6] = '\0';
1045     /* option 1 */
1046     i_pos = snprintf( &ppsz_options[i_options][0], VLC_MAX_MRL, "sout='#transcode{");
1047     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1048
1049     p_entryVideoCodec   = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryVideoCodec" );
1050     p_entryVideoBitrate = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryVideoBitrate" );
1051     p_entryVideoBitrateTolerance = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryVideoBitrateTolerance" );
1052     p_entryVideoKeyFrameInterval = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryVideoKeyFrameInterval" );
1053     
1054     p_video_codec = gtk_entry_get_text(GTK_ENTRY(p_entryVideoCodec));
1055     i_video_bitrate = gtk_spin_button_get_value_as_int(p_entryVideoBitrate);
1056     i_video_bitrate_tolerance = gtk_spin_button_get_value_as_int(p_entryVideoBitrateTolerance);
1057     i_video_keyframe_interval = gtk_spin_button_get_value_as_int(p_entryVideoKeyFrameInterval);
1058     
1059     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "vcodec=%s,", (char*)p_video_codec );
1060     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1061     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "vb=%d,", (int)i_video_bitrate );
1062     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1063     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "vt=%d,", (int)i_video_bitrate_tolerance );
1064     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1065     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "keyint=%d,", (int)i_video_keyframe_interval );
1066     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1067
1068     p_checkVideoDeinterlace = (GtkCheckButton*) lookup_widget( GTK_WIDGET(button), "checkVideoDeinterlace" );
1069     b_video_deinterlace = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_checkVideoDeinterlace));
1070     if (b_video_deinterlace)
1071     {
1072         i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "deinterlace," );
1073         if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1074     }
1075     p_entryAudioCodec   = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryAudioCodec" );
1076     p_entryAudioBitrate = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryAudioBitrate" );
1077
1078     p_audio_codec = gtk_entry_get_text(GTK_ENTRY(p_entryAudioCodec));
1079     i_audio_bitrate = gtk_spin_button_get_value_as_int(p_entryAudioBitrate);
1080
1081     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "acodec=%s,", (char*)p_audio_codec );
1082     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1083     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "ab=%d,", (int)i_audio_bitrate );
1084     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1085     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "channels=1}"/*, (int)i_audio_channels*/ );
1086     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1087
1088     /* option 2 */
1089     i_pos = 0;
1090     i_pos = snprintf( &ppsz_options[i_options++][i_pos], VLC_MAX_MRL - i_pos, "#" );
1091     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1092
1093     p_entryStdAccess = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryStdAccess" );
1094     p_entryStdMuxer  = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryStdMuxer" );
1095     p_entryStdURL = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryStdURL" );
1096     p_entryStdAnnounce = (GtkEntry*) lookup_widget( GTK_WIDGET(button), "entryAnnounceChannel" );
1097     p_entryStdTTL = (GtkSpinButton*) lookup_widget( GTK_WIDGET(button), "entryStdTTL" );
1098
1099     p_std_access = gtk_entry_get_text(GTK_ENTRY(p_entryStdAccess));
1100     p_std_muxer = gtk_entry_get_text(GTK_ENTRY(p_entryStdMuxer));
1101     p_std_url = gtk_entry_get_text(GTK_ENTRY(p_entryStdURL));
1102     p_std_announce = gtk_entry_get_text(GTK_ENTRY(p_entryStdAnnounce));
1103     b_sap_announce = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_checkSAP));
1104     b_slp_announce = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p_checkSLP));
1105
1106     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "std{access=%s,", (char*)p_std_access);
1107     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1108     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "mux=%s,", (char*)p_std_muxer);
1109     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1110     i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "dst=%s", (char*)p_std_url);
1111     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1112
1113     if (strncasecmp( (const char*)p_std_access, "udp", 3)==0)
1114     {
1115         if (b_sap_announce)
1116         {
1117             i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "sap=%s", (char*)p_std_announce);
1118             if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1119         }
1120         if (b_slp_announce)
1121         {
1122             i_pos += snprintf( &ppsz_options[i_options][i_pos], VLC_MAX_MRL - i_pos, "slp=%s", (char*)p_std_announce);
1123             if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1124         }
1125     }
1126
1127     i_std_ttl = gtk_spin_button_get_value_as_int(p_entryStdTTL);
1128
1129     i_pos += snprintf( &ppsz_options[i_options++][i_pos], VLC_MAX_MRL - i_pos, "ttl=%d}", (int)i_std_ttl);
1130     if (i_pos>=VLC_MAX_MRL) ppsz_options[i_options][VLC_MAX_MRL-1] = '\0';
1131
1132     if (user_data != NULL)
1133     {
1134       msg_Dbg(p_intf, "Adding transcoding options to playlist item." );
1135     }
1136     else
1137     {
1138       msg_Dbg(p_intf, "Adding --sout to playlist." );
1139       PlaylistAddItem(GTK_WIDGET(button), (gchar*) &mrl, ppsz_options, i_options);
1140     }
1141 }
1142
1143 void onEntryStdAccessChanged(GtkEditable *editable, gpointer user_data)
1144 {
1145     intf_thread_t *p_intf = GtkGetIntf( editable );
1146
1147     GtkCheckButton *p_checkSAP = NULL;
1148     GtkCheckButton *p_checkSLP = NULL;
1149     GtkEntry       *p_entryStdAccess = NULL;
1150     const gchar    *p_std_access = NULL;    
1151     gboolean        b_announce = FALSE;
1152
1153     p_entryStdAccess = (GtkEntry*) lookup_widget( GTK_WIDGET(editable), "entryStdAccess" );
1154     p_checkSAP = (GtkCheckButton*) lookup_widget( GTK_WIDGET(editable), "checkSAP" );
1155     p_checkSLP = (GtkCheckButton*) lookup_widget( GTK_WIDGET(editable), "checkSLP" );
1156
1157     if ( (p_std_access == NULL) || (p_checkSAP == NULL) || (p_checkSLP == NULL))
1158     {
1159         msg_Err( p_intf, "Access, SAP and SLP widgets not found." );
1160         return;
1161     }
1162     p_std_access = gtk_entry_get_text(GTK_ENTRY(p_entryStdAccess));
1163
1164     b_announce = (strncasecmp( (const char*)p_std_access, "udp", 3) == 0);
1165     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_checkSAP), b_announce);
1166     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_checkSLP), b_announce);
1167 }
1168