]> git.sesse.net Git - vlc/blob - modules/gui/kde/interface.cpp
* all: don't use input_OffsetToTime anymore.
[vlc] / modules / gui / kde / interface.cpp
1 /***************************************************************************
2                           interface.cpp  -  description
3                              -------------------
4     begin                : Sun Mar 25 2001
5     copyright            : (C) 2001 by andres
6     email                : dae@chez.com
7  ***************************************************************************/
8
9 #include "disc.h"
10 #include "info.h"
11 #include "interface.h"
12 #include "net.h"
13 #include "menu.h"
14 #include "slider.h"
15 #include "preferences.h"
16 #include "languagemenu.h"
17
18 #include <iostream>
19
20 #include <kaction.h>
21 #include <kfiledialog.h>
22 #include <klocale.h>
23 #include <kstdaction.h>
24 #include <kurl.h>
25 #include <kurldrag.h>
26 #include <qcursor.h>
27 #include <qdragobject.h>
28 #include <qtimer.h>
29 #include <kdialog.h>
30 #include <kstatusbar.h>
31
32 #define ID_STATUS_MSG       1
33 #define ID_DATE             2
34 #define ID_STREAM_SOURCE    3
35
36 KInterface::KInterface( intf_thread_t *p_intf, QWidget *parent,
37         const char *name ) : KMainWindow(parent,name)
38 {
39     setAcceptDrops(true);
40
41     this->p_intf = p_intf;
42     p_messagesWindow = new KMessagesWindow( p_intf, p_intf->p_sys->p_msg );
43     fDiskDialog = new KDiskDialog( this );
44     fNetDialog = new KNetDialog( this );
45     fTitleMenu = new KTitleMenu( p_intf, this );
46
47     fSlider = new KVLCSlider( QSlider::Horizontal, this );
48     fSlider->setMaxValue(10000);
49     connect( fSlider, SIGNAL( userChanged( int ) ), this,
50              SLOT( slotSliderMoved( int ) ) );
51     connect( fSlider, SIGNAL( valueChanged( int ) ), this,
52              SLOT( slotSliderChanged( int ) ) );
53     connect( fSlider, SIGNAL( sliderMoved( int ) ), this,
54              SLOT( slotSliderChanged( int ) ) );
55     setCentralWidget(fSlider);
56
57     fTimer = new QTimer( this );
58     connect( fTimer, SIGNAL( timeout() ), this, SLOT( slotManage() ) );
59
60     resize( 400, 30 );
61     ///////////////////////////////////////////////////////////////////
62     // call inits to invoke all other construction parts
63     // XXX could we move this up ?
64     initStatusBar();
65     initActions();
66
67     // add certain calls to the popup menu
68     fileOpen->plug( fTitleMenu );
69     fileOpenRecent->plug( fTitleMenu );
70     diskOpen->plug( fTitleMenu );
71     streamOpen->plug( fTitleMenu );
72     play->plug( fTitleMenu );
73     pause->plug( fTitleMenu );
74     slow->plug( fTitleMenu );
75     fast->plug( fTitleMenu );
76     fileQuit->plug( fTitleMenu );
77     fTimer->start( 0, FALSE );
78
79 }
80
81 KInterface::~KInterface()
82 {
83     ;
84 }
85
86 void KInterface::initActions()
87 {
88     languages = new KActionMenu( _( "Languages" ), actionCollection(),
89                                  _("language") );
90     languages->setEnabled( false );
91     languageCollection = new KActionCollection( this );
92     subtitleCollection = new KActionCollection( this );
93     subtitles = new KActionMenu( _( "Subtitles" ), actionCollection(),
94                                  "subtitles" );
95     subtitles->setEnabled( false );
96     fileOpen =
97         KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
98     fileOpenRecent =
99         KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)),
100                                actionCollection());
101     preferences = KStdAction::preferences(this, SLOT(slotShowPreferences()),
102                                           actionCollection());
103     fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()),
104                                 actionCollection());
105     viewToolBar = KStdAction::showToolbar(this, SLOT(slotViewToolBar()),
106                                           actionCollection());
107     viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()),
108                                               actionCollection());
109
110     diskOpen = new KAction( i18n( _("Open &Disk") ), 0, 0, this,
111                             SLOT( slotOpenDisk() ), actionCollection(),
112                             "open_disk" );
113     streamOpen = new KAction( i18n( _("Open &Stream") ), 0, 0, this,
114                               SLOT( slotOpenStream() ), actionCollection(),
115                               "open_stream" );
116     backward = new KAction( i18n( _("&Backward") ), 0, 0, this,
117                             SLOT( slotBackward() ), actionCollection(),
118                             "backward" );
119     stop = new KAction( i18n( _("&Stop") ), 0, 0, this,
120                         SLOT( slotStop() ), actionCollection(), "stop" );
121     play = new KAction( i18n( _("&Play") ), 0, 0, this,
122                         SLOT( slotPlay() ), actionCollection(), "play" );
123     pause = new KAction( i18n( _("P&ause") ), 0, 0, this,
124                          SLOT( slotPause() ), actionCollection(), "pause" );
125     slow = new KAction( i18n( _("&Slow") ), 0, 0, this,
126                         SLOT( slotSlow() ), actionCollection(), "slow" );
127     fast = new KAction( i18n( _("Fas&t") ), 0, 0, this,
128                         SLOT( slotFast() ), actionCollection(), "fast" );
129     prev = new KAction( i18n( _("Prev") ), 0, 0, this,
130                         SLOT( slotPrev() ), actionCollection(), "prev" );
131     next = new KAction( i18n( _("Next") ), 0, 0, this,
132                         SLOT( slotNext() ), actionCollection(), "next" );
133     messages = new KAction( _( "Messages..." ), 0, 0, this,
134                             SLOT( slotShowMessages() ), actionCollection(),
135                             "view_messages");
136     
137     info = new KAction( _( "Stream info..." ), 0, 0, this,
138                         SLOT( slotShowInfo() ), actionCollection(),
139                         "view_stream_info");
140
141     info->setEnabled( false );
142     program = new KActionMenu( _( "Program" ), actionCollection(), "program" );
143     program->setEnabled( false );
144     title = new KActionMenu( _( "Title" ), actionCollection(), "title" );
145     title->setEnabled( false );
146     chapter = new KActionMenu( _( "Chapter" ), actionCollection(), "chapter" );
147     chapter->setEnabled( false );
148     fileOpen->setStatusText(i18n(_("Opens an existing document")));
149     fileOpenRecent->setStatusText(i18n(_("Opens a recently used file")));
150     fileQuit->setStatusText(i18n(_("Quits the application")));
151     viewToolBar->setStatusText(i18n(_("Enables/disables the toolbar")));
152     viewStatusBar->setStatusText(i18n(_("Enables/disables the status bar")));
153
154     diskOpen->setStatusText( i18n( _("Opens a disk") ) );
155     streamOpen->setStatusText( i18n( _("Opens a network stream") ) );
156     backward->setStatusText( i18n( _("Backward") ) );
157     stop->setStatusText( i18n( _("Stops playback") ) );
158     play->setStatusText( i18n( _("Starts playback") ) );
159     pause->setStatusText( i18n( _("Pauses playback") ) );
160     slow->setStatusText( i18n( _("Slow") ) );
161     fast->setStatusText( i18n( _("Fast") ) );
162     prev->setStatusText( i18n( _("Prev") ) );
163     next->setStatusText( i18n( _("Next") ) );
164     // use the absolute path to your ktestui.rc file for testing purpose in createGUI();
165     char *psz_uifile = config_GetPsz( p_intf, "kde-uirc" );
166     createGUI( psz_uifile );
167 //    createGUI( "./modules/gui/kde/ui.rc" );
168 }
169
170 void KInterface::initStatusBar()
171 {
172   ///////////////////////////////////////////////////////////////////
173   // STATUSBAR
174   // TODO: add your own items you need for displaying current application status.
175     statusBar()->insertItem(i18n(_("Ready.")), ID_STATUS_MSG, 1, false);
176     statusBar()->setItemAlignment( ID_STATUS_MSG, AlignLeft | AlignVCenter );
177     statusBar()->insertItem( "0:00:00", ID_DATE, 0, true );
178 }
179
180 /////////////////////////////////////////////////////////////////////
181 // SLOT IMPLEMENTATION
182 /////////////////////////////////////////////////////////////////////
183 void KInterface::slotShowMessages()
184 {
185     p_messagesWindow->show();
186 }
187
188 void KInterface::slotShowInfo()
189 {
190     if ( p_intf->p_sys->p_input )
191     {
192         new KInfoWindow(p_intf, p_intf->p_sys->p_input);
193     }
194 }
195
196 void KInterface::slotFileOpen()
197 {
198     playlist_t *p_playlist;
199
200     slotStatusMsg( i18n( _("Opening file...") ) );
201     KURL url=KFileDialog::getOpenURL( QString::null,
202             i18n( "*|All files" ), this, i18n( _("Open File...") ) );
203
204     if( !url.isEmpty() )
205     {
206         p_playlist = (playlist_t *)
207             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
208         if( p_playlist )
209         {
210             fileOpenRecent->addURL( url );
211             playlist_Add( p_playlist, url.path(), url.path(), 
212                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
213             vlc_object_release( p_playlist );
214         }
215     }
216
217     slotStatusMsg( i18n( _("Ready.") ) );
218 }
219
220 void KInterface::slotFileOpenRecent(const KURL& url)
221 {
222   slotStatusMsg(i18n(_("Opening file...")));
223   slotStatusMsg(i18n(_("Ready.")));
224 }
225
226 void KInterface::slotFileQuit()
227 {
228     slotStatusMsg(i18n(_("Exiting...")));
229     p_intf->p_vlc->b_die = VLC_TRUE;
230     slotStatusMsg(i18n(_("Ready.")));
231 }
232
233 void KInterface::slotViewToolBar()
234 {
235   slotStatusMsg(i18n(_("Toggling toolbar...")));
236   ///////////////////////////////////////////////////////////////////
237   // turn Toolbar on or off
238   if(!viewToolBar->isChecked())
239   {
240     toolBar("mainToolBar")->hide();
241   }
242   else
243   {
244     toolBar("mainToolBar")->show();
245   }        
246
247   slotStatusMsg(i18n(_("Ready.")));
248 }
249
250 void KInterface::slotViewStatusBar()
251 {
252   slotStatusMsg(i18n(_("Toggle the status bar...")));
253   ///////////////////////////////////////////////////////////////////
254   //turn Statusbar on or off
255   if(!viewStatusBar->isChecked())
256   {
257     statusBar()->hide();
258   }
259   else
260   {
261     statusBar()->show();
262   }
263
264   slotStatusMsg(i18n(_("Ready.")));
265 }
266
267 void KInterface::slotShowPreferences()
268 {
269     // Do something
270     KPreferences(this->p_intf, "main", this, "preferences");
271 }
272
273 void KInterface::slotStatusMsg(const QString &text)
274 {
275   ///////////////////////////////////////////////////////////////////
276   // change status message permanently
277   statusBar()->clear();
278   statusBar()->changeItem(text, ID_STATUS_MSG);
279 }
280
281 void KInterface::slotManage()
282 {
283     p_messagesWindow->update();
284 //    p_intf->p_sys->p_app->processEvents();
285     vlc_mutex_lock( &p_intf->change_lock );
286
287     /* Update the input */
288     if( p_intf->p_sys->p_input == NULL )
289     {
290         p_intf->p_sys->p_input = (input_thread_t *)
291                 vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
292         if ( p_intf->p_sys->p_input )
293         {
294             languages->setEnabled( true );
295             subtitles->setEnabled( true );
296             info->setEnabled( true );
297         }
298             
299     }
300     else if( p_intf->p_sys->p_input->b_dead )
301     {
302         vlc_object_release( p_intf->p_sys->p_input );
303         p_intf->p_sys->p_input = NULL;
304         languages->setEnabled( false );
305         subtitles->setEnabled( false );
306         info->setEnabled( false );
307     }
308
309     /* If the "display popup" flag has changed */
310     if( p_intf->b_menu_change )
311     {
312         fTitleMenu->popup( ( QCursor::pos() ) );
313         p_intf->b_menu_change = 0;
314     }
315
316     if( p_intf->p_sys->p_input )
317     {
318         input_thread_t *p_input = p_intf->p_sys->p_input;
319                 
320         vlc_mutex_lock( &p_input->stream.stream_lock );
321         if( !p_input->b_die )
322         {
323             /* New input or stream map change */
324             if( p_input->stream.b_changed )
325             {
326                 //            E_(GtkModeManage)( p_intf );
327                 //GtkSetupMenus( p_intf );
328                 slotUpdateLanguages();
329
330                 p_intf->p_sys->b_playing = 1;
331                 p_input->stream.b_changed = 0;
332             }
333
334             /* Manage the slider. fSlider->setValue triggers
335              * slotSliderChanged which needs to grab the stream lock*/
336 #define p_area p_input->stream.p_selected_area
337             if( p_area->i_size ) {
338                 vlc_mutex_unlock( &p_input->stream.stream_lock );
339                 fSlider->setValue( ( 10000 * p_area->i_tell )
340                                    / p_area->i_size );
341                 vlc_mutex_lock( &p_input->stream.stream_lock );
342
343             }
344 #undef p_area
345             
346             //         if( p_intf->p_sys->i_part !=
347             //    p_input->stream.p_selected_area->i_part )
348             //{
349                 //      p_intf->p_sys->b_chapter_update = 1;
350                 //GtkSetupMenus( p_intf );
351             //}
352         }
353         vlc_mutex_unlock( &p_input->stream.stream_lock );
354
355     }
356     
357     else if( p_intf->p_sys->b_playing && !p_intf->b_die )
358     {
359         //E_(GtkModeManage)( p_intf );
360         p_intf->p_sys->b_playing = 0;
361     }
362
363     if( p_intf->b_die )
364     {
365         p_intf->p_sys->p_app->quit();
366     }
367
368     vlc_mutex_unlock( &p_intf->change_lock );
369     msleep( 100 );
370
371 }
372
373 void KInterface::slotSliderMoved( int position )
374 {
375     if( p_intf->p_sys->p_input )
376     {
377         // XXX is this locking really useful ?
378         vlc_mutex_lock( &p_intf->change_lock );
379
380         var_SetFloat( p_intf->p_sys->p_input, "position",
381                        (double)position / 10000.0 );
382         vlc_mutex_unlock( &p_intf->change_lock );
383     }
384 }
385
386 void KInterface::slotUpdateLanguages()
387 {
388
389     es_descriptor_t *   p_spu_es;
390     es_descriptor_t *   p_audio_es;
391     /* look for selected ES */
392     p_audio_es = NULL;
393     p_spu_es = NULL;
394
395     for( unsigned int i = 0 ;
396          i < p_intf->p_sys->p_input->stream.i_selected_es_number ;
397          i++
398         )
399     {
400         if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat
401             == AUDIO_ES )
402         {
403             p_audio_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
404         }
405
406         if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
407         {
408             p_spu_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
409         }
410     }
411     languages->setEnabled( false );
412     subtitles->setEnabled( false );
413     languageCollection->clear();
414     subtitleCollection->clear();
415     languages->popupMenu()->clear();
416     subtitles->popupMenu()->clear();
417     /* audio menus */
418     /* find audio root menu */
419     languageMenus( languages, p_audio_es, AUDIO_ES );
420
421     /* sub picture menus */
422     /* find spu root menu */
423     languageMenus( subtitles, p_spu_es, SPU_ES );
424
425 }
426
427
428 /*
429  * called with stream lock
430  */
431 void KInterface::languageMenus(KActionMenu *root, es_descriptor_t *p_es,
432                           int i_cat)
433 {
434     int i_item = 0;
435     if ( i_cat != AUDIO_ES )
436     {
437         KLanguageMenuAction *p_item =
438             new KLanguageMenuAction( p_intf, _( "Off" ), 0, this );
439         subtitleCollection->insert( p_item );
440         root->insert( p_item );
441         root->insert( new KActionSeparator( this ) );
442         p_item->setExclusiveGroup( QString().sprintf( "%d", i_cat ) );
443         p_item->setChecked( p_es == 0 );
444     }
445     
446 #define ES p_intf->p_sys->p_input->stream.pp_es[i]
447     /* create a set of language buttons and append them to the container */
448     for( unsigned int i = 0 ;
449          i < p_intf->p_sys->p_input->stream.i_es_number ;
450          i++ )
451     {
452         if( ( ES->i_cat == i_cat ) &&
453             ( !ES->p_pgrm ||
454               ES->p_pgrm ==
455                  p_intf->p_sys->p_input->stream.p_selected_program ) )
456         {
457             i_item++;
458             QString name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc;
459             if( name.isEmpty() )
460             {
461                 name.sprintf( "Language %d", i_item );
462             }
463             KLanguageMenuAction *p_item;
464             if ( i_cat == AUDIO_ES )
465             {
466                 p_item = new KLanguageMenuAction( p_intf, name, ES,
467                                                   this );
468                 languageCollection->insert(p_item);
469             }
470             else
471             {
472                 p_item = new KLanguageMenuAction( p_intf, name, ES,
473                                                   this );
474                 subtitleCollection->insert(p_item);
475             }
476             p_item->setExclusiveGroup( QString().sprintf( "%d", i_cat ) );
477             root->insert( p_item );
478             
479             if( p_es == p_intf->p_sys->p_input->stream.pp_es[i] )
480             {
481                 /* don't lose p_item when we append into menu */
482                 //p_item_active = p_item;
483                 p_item->setChecked( true );
484             }
485             connect( p_item, SIGNAL( toggled( bool, es_descriptor_t * ) ),
486                      this, SLOT( slotSetLanguage( bool, es_descriptor_t * ) ));
487
488         }
489     }
490
491     root->setEnabled( true );
492 }
493
494
495 void KInterface::slotSetLanguage( bool on, es_descriptor_t *p_es )
496 {
497     input_ToggleES( p_intf->p_sys->p_input, p_es, on );
498 }
499
500 void KInterface::slotSliderChanged( int position )
501 {
502     if( p_intf->p_sys->p_input != NULL )
503     {
504         char psz_time[ MSTRTIME_MAX_SIZE ];
505         int64_t i_seconds;
506
507         i_seconds = var_GetTime( p_intf->p_sys->p_input, "time" ) / I64C(1000000 );
508         secstotimestr( psz_time, i_seconds );
509
510         statusBar()->changeItem( psz_time, ID_DATE );
511      }
512 }
513
514 void KInterface::slotOpenDisk()
515 {
516     playlist_t *p_playlist;
517     int r = fDiskDialog->exec();
518     if ( r )
519     {
520         // Build source name
521         QString source;
522         source += fDiskDialog->type();
523         source += ':';
524         source += fDiskDialog->device();
525
526         source += '@';
527         source += fDiskDialog->title();
528         source += ',';
529         source += fDiskDialog->chapter();
530
531         p_playlist = (playlist_t *)
532             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
533         if( p_playlist )
534         {
535             // add it to playlist
536             playlist_Add( p_playlist, source.latin1(), source.latin1(),
537                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
538             vlc_object_release( p_playlist );
539         }
540     }
541 }
542
543 void KInterface::slotOpenStream()
544 {
545     playlist_t *p_playlist;
546     int r = fNetDialog->exec();
547     if ( r )
548     {
549         // Build source name
550         QString source;
551         source += fNetDialog->protocol();
552         source += "://";
553         source += fNetDialog->server();
554         source += ":";
555         source += QString().setNum( fNetDialog->port() );
556
557         p_playlist = (playlist_t *)
558             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
559         if( p_playlist )
560         {
561             // add it to playlist
562             playlist_Add( p_playlist, source.latin1(), source.latin1(),
563                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
564             vlc_object_release( p_playlist );
565         }
566     }
567 }
568
569 void KInterface::slotPlay()
570 {
571     if( p_intf->p_sys->p_input )
572     {
573         var_SetInteger( p_intf->p_sys->p_input, "state", PLAYING_S );
574     }
575 }
576
577 void KInterface::slotPause()
578 {
579     if ( p_intf->p_sys->p_input )
580     {
581         var_SetInteger( p_intf->p_sys->p_input, "state", PAUSE_S );
582     }
583 }
584
585 void KInterface::slotStop()
586 {
587     playlist_t *p_playlist = (playlist_t *)
588             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
589     if( p_playlist )
590     {
591         playlist_Stop( p_playlist );
592         vlc_object_release( p_playlist );
593     }
594 }
595
596 void KInterface::slotBackward()
597 {
598     msg_Err( p_intf, "KInterface::slotBackward() - Unimplemented" );
599 }
600
601 void KInterface::slotPrev()
602 {
603     playlist_t *p_playlist = (playlist_t *)
604             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
605     if( p_playlist )
606     {
607         playlist_Prev( p_playlist );
608         vlc_object_release( p_playlist );
609     }
610 }
611
612 void KInterface::slotNext()
613 {
614     playlist_t *p_playlist = (playlist_t *)
615             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
616     if( p_playlist )
617     {
618         playlist_Next( p_playlist );
619         vlc_object_release( p_playlist );
620     }
621 }
622
623 void KInterface::slotSlow()
624 {
625     if( p_intf->p_sys->p_input != NULL )
626     {
627         var_SetVoid( p_intf->p_sys->p_input, "rate-slower" );
628     }
629 }
630
631 void KInterface::slotFast()
632 {
633     if( p_intf->p_sys->p_input != NULL )
634     {
635         var_SetVoid( p_intf->p_sys->p_input, "rate-faster" );
636     }
637 }
638
639 void KInterface::dragEnterEvent( QDragEnterEvent *event )
640 {
641     event->accept( QUriDrag::canDecode( event ) );
642 }
643
644 void KInterface::dropEvent( QDropEvent *event )
645 {
646     KURL::List urlList;
647
648     playlist_t *p_playlist = (playlist_t *)
649             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
650     if( p_playlist == NULL )
651     {
652         return;
653     }
654
655     if ( KURLDrag::decode( event, urlList ) )
656     {
657         for ( KURL::List::ConstIterator i = urlList.begin(); i != urlList.end(); i++ )
658         {
659             // XXX add a private function to add a KURL with checking
660             // actually a whole class for core abstraction would be neat
661             if( !(*i).isEmpty() )
662             {
663                 fileOpenRecent->addURL( *i );
664                 playlist_Add( p_playlist, (*i).path(), (*i).path(),
665                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
666             }
667         }
668     }
669
670     vlc_object_release( p_playlist );
671 }