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