* Make vlc compiling !
[vlc.git] / modules / gui / familiar / callbacks.c
1 /*****************************************************************************
2  * callbacks.c : Callbacks for the Familiar Linux Gtk+ plugin.
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id: callbacks.c,v 1.24 2003/07/31 20:47:09 reno Exp $
6  *
7  * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <sys/types.h>                                              /* off_t */
28 #include <stdlib.h>
29 #include <vlc/vlc.h>
30 #include <vlc/intf.h>
31 #include <vlc/vout.h>
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <dirent.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38
39 #ifdef HAVE_CONFIG_H
40 #  include <config.h>
41 #endif
42
43 #include <gtk/gtk.h>
44
45 #include "playlist.h"
46 #include "callbacks.h"
47 #include "interface.h"
48 #include "support.h"
49 #include "familiar.h"
50
51 static char* get_file_perm(const char *path);
52
53 /*****************************************************************************
54  * Useful function to retrieve p_intf
55  ****************************************************************************/
56 void * E_(__GtkGetIntf)( GtkWidget * widget )
57 {
58     void *p_data;
59
60     if( GTK_IS_MENU_ITEM( widget ) )
61     {
62         /* Look for a GTK_MENU */
63         while( widget->parent && !GTK_IS_MENU( widget ) )
64         {
65             widget = widget->parent;
66         }
67
68         /* Maybe this one has the data */
69         p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
70         if( p_data )
71         {
72             return p_data;
73         }
74
75         /* Otherwise, the parent widget has it */
76         widget = gtk_menu_get_attach_widget( GTK_MENU( widget ) );
77     }
78
79     /* We look for the top widget */
80     widget = gtk_widget_get_toplevel( GTK_WIDGET( widget ) );
81
82     p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
83
84     return p_data;
85 }
86
87 /*****************************************************************************
88  * Helper functions for URL changes in Media and Preferences notebook pages.
89  ****************************************************************************/
90 void MediaURLOpenChanged( GtkWidget *widget, gchar *psz_url )
91 {
92     intf_thread_t *p_intf = GtkGetIntf( widget );
93     playlist_t *p_playlist;
94
95     // Add p_url to playlist .... but how ?
96     p_playlist = (playlist_t *)
97              vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
98
99     if( p_playlist ==  NULL)
100     {
101         return;
102     }
103     
104     if( p_playlist )
105     {
106         if (p_intf->p_sys->b_autoplayfile)
107         {
108                 playlist_Add( p_playlist, (char*)psz_url, 0, 0,
109                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
110         }
111         else
112         {
113             playlist_Add( p_playlist, (char*)psz_url, 0, 0,
114                           PLAYLIST_APPEND, PLAYLIST_END );
115         }
116         vlc_object_release(  p_playlist );
117         FamiliarRebuildCList( p_intf->p_sys->p_clistplaylist, p_playlist);
118     }
119 }
120
121 /*****************************************************************
122  * Read directory helper function.
123  ****************************************************************/
124 void ReadDirectory( GtkCList *clist, char *psz_dir )
125 {
126     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(clist) );
127     struct dirent **namelist;
128     int n=-1, status=-1;
129
130     msg_Dbg(p_intf, "changing to dir %s", psz_dir);
131     if (psz_dir)
132     {
133        status = chdir(psz_dir);
134        if (status<0)
135           msg_Err( p_intf, "permision denied" );                        
136     }
137     n = scandir(".", &namelist, 0, alphasort);
138     
139     if (n<0)
140         perror("scandir");
141     else
142     {
143         int i, ctr=0;
144         gchar *ppsz_text[5];
145
146         msg_Dbg( p_intf, "updating interface" );
147         gtk_clist_freeze( clist );
148         gtk_clist_clear( clist );
149
150         /* XXX : kludge temporaire pour yopy */
151         ppsz_text[0]="..";
152         ppsz_text[1] = get_file_perm("..");
153         ppsz_text[2] = "";
154         ppsz_text[3] = "";
155         ppsz_text[4] = "";
156         gtk_clist_insert( GTK_CLIST(clist), ctr++, ppsz_text );
157         /* /kludge */                
158         
159         for (i=0; i<n; i++)
160         {
161             if (namelist[i]->d_name[0] != '.')
162             {
163                 /* This is a list of strings. */
164                 ppsz_text[0] = namelist[i]->d_name;
165                 ppsz_text[1] = get_file_perm(namelist[i]->d_name);
166                 ppsz_text[2] = "";
167                 ppsz_text[3] = "";
168                 ppsz_text[4] = "";
169                 //            msg_Dbg(p_intf, "(%d) file: %s permission: %s", i, ppsz_text[0], ppsz_text[1] );
170                 gtk_clist_insert( GTK_CLIST(clist), ctr++, ppsz_text );
171             }
172         }
173         gtk_clist_thaw( clist );
174         free(namelist);
175     }
176
177     /* now switch to the "file" tab */
178     if (p_intf->p_sys->p_mediabook)
179     {
180        gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_mediabook) );
181        gtk_notebook_set_page(p_intf->p_sys->p_mediabook,0);
182     }
183 }
184
185 static char* get_file_perm(const char *path)
186 {
187     struct stat st;
188     char *perm;
189
190     perm = (char *) malloc(sizeof(char)*10);
191     strncpy( perm, "----------", sizeof("----------"));
192     if (lstat(path, &st)==0)
193     {
194         if (S_ISLNK(st.st_mode))
195             perm[0]= 'l';
196         else if (S_ISDIR(st.st_mode))
197             perm[0]= 'd';
198         else if (S_ISCHR(st.st_mode))
199             perm[0]= 'c';
200         else if (S_ISBLK(st.st_mode))
201             perm[0]= 'b';
202         else if (S_ISFIFO(st.st_mode))
203             perm[0]= 'f';
204         else if (S_ISSOCK(st.st_mode))
205             perm[0]= 's';
206         else if (S_ISREG(st.st_mode))
207             perm[0]= '-';
208         else /* Unknown type is an error */
209             perm[0]= '?';
210         /* Get file permissions */
211         /* User */
212         if (st.st_mode & S_IRUSR)
213             perm[1]= 'r';
214         if (st.st_mode & S_IWUSR)
215             perm[2]= 'w';
216         if (st.st_mode & S_IXUSR)
217         {
218             if (st.st_mode & S_ISUID)
219                 perm[3] = 's';
220             else
221                 perm[3]= 'x';
222         }
223         else if (st.st_mode & S_ISUID)
224             perm[3] = 'S';
225         /* Group */
226         if (st.st_mode & S_IRGRP)
227             perm[4]= 'r';
228         if (st.st_mode & S_IWGRP)
229             perm[5]= 'w';
230         if (st.st_mode & S_IXGRP)
231         {
232             if (st.st_mode & S_ISGID)
233                 perm[6] = 's';
234             else
235                 perm[6]= 'x';
236         }
237         else if (st.st_mode & S_ISGID)
238             perm[6] = 'S';
239         /* Other */
240         if (st.st_mode & S_IROTH)
241             perm[7]= 'r';
242         if (st.st_mode & S_IWOTH)
243             perm[8]= 'w';
244         if (st.st_mode & S_IXOTH)
245         {
246             // 'sticky' bit
247             if (st.st_mode &S_ISVTX)
248                 perm[9] = 't';
249             else
250                 perm[9]= 'x';
251         }
252         else if (st.st_mode &S_ISVTX)
253             perm[9]= 'T';
254     }
255     return perm;
256 }
257
258 /*
259  * Main interface callbacks
260  */
261
262 gboolean FamiliarExit( GtkWidget       *widget,
263                        gpointer         user_data )
264 {
265     intf_thread_t *p_intf = GtkGetIntf( widget );
266
267     vlc_mutex_lock( &p_intf->change_lock );
268     p_intf->p_vlc->b_die = VLC_TRUE;
269     vlc_mutex_unlock( &p_intf->change_lock );
270
271     return TRUE;
272 }
273
274 void
275 on_toolbar_open_clicked                (GtkButton       *button,
276                                         gpointer         user_data)
277 {
278     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET( button ) );
279
280     if (p_intf->p_sys->p_notebook)
281     {
282        gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
283        gtk_notebook_set_page(p_intf->p_sys->p_notebook,0);
284     }
285     if (p_intf->p_sys->p_mediabook)
286     {
287        gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_mediabook) );
288        gtk_notebook_set_page(p_intf->p_sys->p_mediabook,0);
289     }
290     gdk_window_raise( p_intf->p_sys->p_window->window );
291     if (p_intf->p_sys->p_clist)
292     {
293        ReadDirectory(p_intf->p_sys->p_clist, ".");
294     }
295 }
296
297
298 void
299 on_toolbar_preferences_clicked         (GtkButton       *button,
300                                         gpointer         user_data)
301 {
302     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET( button ) );
303
304     if (p_intf->p_sys->p_notebook)
305     {
306        gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
307        gtk_notebook_set_page(p_intf->p_sys->p_notebook,2);
308     }
309     gdk_window_raise( p_intf->p_sys->p_window->window );
310 }
311
312
313 void
314 on_toolbar_rewind_clicked              (GtkButton       *button,
315                                         gpointer         user_data)
316 {
317     intf_thread_t *  p_intf = GtkGetIntf( button );
318
319     if( p_intf->p_sys->p_input != NULL )
320     {
321         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
322     }
323 }
324
325
326 void
327 on_toolbar_pause_clicked               (GtkButton       *button,
328                                         gpointer         user_data)
329 {
330     intf_thread_t *  p_intf = GtkGetIntf( button );
331
332     if( p_intf->p_sys->p_input != NULL )
333     {
334         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
335     }
336 }
337
338
339 void
340 on_toolbar_play_clicked                (GtkButton       *button,
341                                         gpointer         user_data)
342 {
343      intf_thread_t *  p_intf = GtkGetIntf( GTK_WIDGET( button ) );
344      playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
345
346      if( p_playlist == NULL )
347      {
348          /* Display open page */
349          on_toolbar_open_clicked(button,user_data);
350      }
351
352      /* If the playlist is empty, open a file requester instead */
353      vlc_mutex_lock( &p_playlist->object_lock );
354      if( p_playlist->i_size )
355      {
356          vlc_mutex_unlock( &p_playlist->object_lock );
357          playlist_Play( p_playlist );
358          vlc_object_release( p_playlist );
359          gdk_window_lower( p_intf->p_sys->p_window->window );
360      }
361      else
362      {
363          vlc_mutex_unlock( &p_playlist->object_lock );
364          vlc_object_release( p_playlist );
365          /* Display open page */
366          on_toolbar_open_clicked(button,user_data);
367     }
368 }
369
370
371 void
372 on_toolbar_stop_clicked                (GtkButton       *button,
373                                         gpointer         user_data)
374 {
375     intf_thread_t *  p_intf = GtkGetIntf( GTK_WIDGET( button ) );
376     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
377                                                        FIND_ANYWHERE );
378     if( p_playlist)
379     {
380         playlist_Stop( p_playlist );
381         vlc_object_release( p_playlist );
382         gdk_window_raise( p_intf->p_sys->p_window->window );
383     }
384 }
385
386
387 void
388 on_toolbar_forward_clicked             (GtkButton       *button,
389                                         gpointer         user_data)
390 {
391     intf_thread_t *  p_intf = GtkGetIntf( button );
392
393     if( p_intf->p_sys->p_input != NULL )
394     {
395         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
396     }
397 }
398
399 void
400 on_toolbar_playlist_clicked            (GtkButton       *button,
401                                         gpointer         user_data)
402 {
403     intf_thread_t *p_intf = GtkGetIntf( GTK_WIDGET(button) );
404
405     // Toggle notebook
406     if (p_intf->p_sys->p_notebook)
407     {
408         gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
409         gtk_notebook_set_page(p_intf->p_sys->p_notebook,1);
410     }
411     gdk_window_raise( p_intf->p_sys->p_window->window );
412 }
413
414
415 void
416 on_toolbar_about_clicked               (GtkButton       *button,
417                                         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,3);
426     }
427     gdk_window_raise( p_intf->p_sys->p_window->window );
428 }
429
430
431 void
432 on_comboURL_entry_changed              (GtkEditable     *editable,
433                                         gpointer         user_data)
434 {
435     intf_thread_t * p_intf = GtkGetIntf( GTK_WIDGET(editable) );
436     gchar *       psz_url;
437     struct stat st;
438
439     
440     psz_url = gtk_entry_get_text(GTK_ENTRY(editable));
441 /*    if( (strncmp("file://",(const char *) psz_url,7)==0) ||
442         (strncmp("udp://",(const char *) psz_url,6)==0) ||
443         (strncmp("udp4://",(const char *) psz_url,7)==0) ||
444         (strncmp("udp6://",(const char *) psz_url,7)==0) ||
445         (strncmp("udpstream://",(const char *) psz_url,12)==0) ||
446         (strncmp("rtp://",(const char *) psz_url,6)==0) ||
447         (strncmp("rtp4://",(const char *) psz_url,7)==0) ||
448         (strncmp("rtp6://",(const char *) psz_url,7)==0) ||
449         (strncmp("rtpstream://",(const char *) psz_url,12)==0) ||
450         (strncmp("ftp://",(const char *) psz_url,6)==0) ||
451         (strncmp("mms://",(const char *) psz_url,6)==0) ||
452         (strncmp("http://",(const char *) psz_url,7)==0) )
453     {
454         MediaURLOpenChanged(GTK_WIDGET(editable), psz_url);
455     }
456     else */
457     if (stat((char*)psz_url, &st)==0)
458     {
459         if (S_ISDIR(st.st_mode))
460         {
461             if (!p_intf->p_sys->p_clist)
462                 msg_Err(p_intf, "p_clist pointer invalid!!" );
463             ReadDirectory(p_intf->p_sys->p_clist, psz_url);
464         }
465         else if( (S_ISLNK(st.st_mode)) || (S_ISCHR(st.st_mode)) ||
466             (S_ISBLK(st.st_mode)) || (S_ISFIFO(st.st_mode))||
467             (S_ISSOCK(st.st_mode))|| (S_ISREG(st.st_mode)) )
468         {
469             MediaURLOpenChanged(GTK_WIDGET(editable), psz_url);
470         }
471     }
472 }
473
474
475 void
476 on_clistmedia_click_column             (GtkCList        *clist,
477                                         gint             column,
478                                         gpointer         user_data)
479 {
480     static GtkSortType sort_type = GTK_SORT_ASCENDING;
481
482     // Should sort on column
483     switch(sort_type)
484     {
485         case GTK_SORT_ASCENDING:
486             sort_type = GTK_SORT_DESCENDING;
487             break;
488         case GTK_SORT_DESCENDING:
489             sort_type = GTK_SORT_ASCENDING;
490             break;
491     }
492     gtk_clist_freeze( clist );
493     gtk_clist_set_sort_type( clist, sort_type );
494     gtk_clist_sort( clist );
495     gtk_clist_thaw( clist );
496 }
497
498
499 void
500 on_clistmedia_select_row               (GtkCList        *clist,
501                                         gint             row,
502                                         gint             column,
503                                         GdkEvent        *event,
504                                         gpointer         user_data)
505 {
506     intf_thread_t * p_intf = GtkGetIntf( GTK_WIDGET(clist) );
507     gchar *text[2];
508     gint ret;
509     struct stat st;
510
511     if (!p_intf->p_sys->p_clist)
512                 msg_Err(p_intf, "p_clist pointer is invalid.");
513     ret = gtk_clist_get_text (p_intf->p_sys->p_clist, row, 0, text);
514     if (ret)
515     {
516         if (stat((char*)text[0], &st)==0)
517         {
518             if (S_ISDIR(st.st_mode))
519                ReadDirectory(p_intf->p_sys->p_clist, text[0]);
520             else if( (S_ISLNK(st.st_mode)) || (S_ISCHR(st.st_mode)) ||
521                      (S_ISBLK(st.st_mode)) || (S_ISFIFO(st.st_mode))||
522                      (S_ISSOCK(st.st_mode))|| (S_ISREG(st.st_mode)) )
523             {
524                MediaURLOpenChanged(GTK_WIDGET(p_intf->p_sys->p_clist), text[0]);
525             }
526        }
527     }
528 }
529
530
531 void
532 on_cbautoplay_toggled                  (GtkToggleButton *togglebutton,
533                                         gpointer         user_data)
534 {
535 }
536
537
538 gboolean
539 on_familiar_delete_event               (GtkWidget       *widget,
540                                         GdkEvent        *event,
541                                         gpointer         user_data)
542 {
543     FamiliarExit( GTK_WIDGET( widget ), user_data );
544     return TRUE;
545 }
546
547 /* Slider Management */
548
549 gboolean
550 FamiliarSliderRelease                  (GtkWidget       *widget,
551                                         GdkEventButton  *event,
552                                         gpointer         user_data)
553 {
554     intf_thread_t *p_intf = GtkGetIntf( widget );
555
556     vlc_mutex_lock( &p_intf->change_lock );
557     p_intf->p_sys->b_slider_free = 1;
558     vlc_mutex_unlock( &p_intf->change_lock );
559
560     return FALSE;
561 }
562
563
564 gboolean
565 FamiliarSliderPress                    (GtkWidget       *widget,
566                                         GdkEventButton  *event,
567                                         gpointer         user_data)
568 {
569     intf_thread_t *p_intf = GtkGetIntf( widget );
570
571     vlc_mutex_lock( &p_intf->change_lock );
572     p_intf->p_sys->b_slider_free = 0;
573     vlc_mutex_unlock( &p_intf->change_lock );
574
575     return FALSE;
576 }
577
578
579
580
581 void
582 FamiliarMrlGo                          (GtkButton       *button,
583                                         gpointer         user_data)
584 {
585     intf_thread_t *  p_intf = GtkGetIntf( button );
586
587     MediaURLOpenChanged( GTK_WIDGET( button ),
588             gtk_entry_get_text(p_intf->p_sys->p_mrlentry ) );
589 }
590
591
592
593 void
594 FamiliarPreferencesApply               (GtkButton       *button,
595                                         gpointer         user_data)
596 {
597     intf_thread_t * p_intf = GtkGetIntf( GTK_WIDGET(button) );
598     
599     GtkToggleButton * p_autopl_button = GTK_GET( TOGGLE_BUTTON, "cbautoplay" );
600     if (gtk_toggle_button_get_active(p_autopl_button))
601     {
602         p_intf->p_sys->b_autoplayfile = 1;
603     }
604     else
605     {
606         p_intf->p_sys->b_autoplayfile = 0;
607     }
608 }
609