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