1 /***************************************************************************
2 interface.cpp - description
4 begin : Sun Mar 25 2001
5 copyright : (C) 2001 by andres
7 ***************************************************************************/
11 #include "interface.h"
15 #include "preferences.h"
16 #include "languagemenu.h"
21 #include <kfiledialog.h>
23 #include <kstdaction.h>
27 #include <qdragobject.h>
30 #include <kstatusbar.h>
32 #define ID_STATUS_MSG 1
34 #define ID_STREAM_SOURCE 3
36 KInterface::KInterface( intf_thread_t *p_intf, QWidget *parent,
37 const char *name ) : KMainWindow(parent,name)
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 );
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);
57 fTimer = new QTimer( this );
58 connect( fTimer, SIGNAL( timeout() ), this, SLOT( slotManage() ) );
61 ///////////////////////////////////////////////////////////////////
62 // call inits to invoke all other construction parts
63 // XXX could we move this up ?
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 );
81 KInterface::~KInterface()
86 void KInterface::initActions()
88 languages = new KActionMenu( _( "Languages" ), actionCollection(),
90 languages->setEnabled( false );
91 languageCollection = new KActionCollection( this );
92 subtitleCollection = new KActionCollection( this );
93 subtitles = new KActionMenu( _( "Subtitles" ), actionCollection(),
95 subtitles->setEnabled( false );
97 KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
99 KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)),
101 preferences = KStdAction::preferences(this, SLOT(slotShowPreferences()),
103 fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()),
105 viewToolBar = KStdAction::showToolbar(this, SLOT(slotViewToolBar()),
107 viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()),
110 diskOpen = new KAction( i18n( _("Open &Disk") ), 0, 0, this,
111 SLOT( slotOpenDisk() ), actionCollection(),
113 streamOpen = new KAction( i18n( _("Open &Stream") ), 0, 0, this,
114 SLOT( slotOpenStream() ), actionCollection(),
116 backward = new KAction( i18n( _("&Backward") ), 0, 0, this,
117 SLOT( slotBackward() ), actionCollection(),
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(),
137 info = new KAction( _( "Stream info..." ), 0, 0, this,
138 SLOT( slotShowInfo() ), actionCollection(),
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")));
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" );
170 void KInterface::initStatusBar()
172 ///////////////////////////////////////////////////////////////////
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 );
180 /////////////////////////////////////////////////////////////////////
181 // SLOT IMPLEMENTATION
182 /////////////////////////////////////////////////////////////////////
183 void KInterface::slotShowMessages()
185 p_messagesWindow->show();
188 void KInterface::slotShowInfo()
190 if ( p_intf->p_sys->p_input )
192 new KInfoWindow(p_intf, p_intf->p_sys->p_input);
196 void KInterface::slotFileOpen()
198 playlist_t *p_playlist;
200 slotStatusMsg( i18n( _("Opening file...") ) );
201 KURL url=KFileDialog::getOpenURL( QString::null,
202 i18n( "*|All files" ), this, i18n( _("Open File...") ) );
206 p_playlist = (playlist_t *)
207 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
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 );
217 slotStatusMsg( i18n( _("Ready.") ) );
220 void KInterface::slotFileOpenRecent(const KURL& url)
222 slotStatusMsg(i18n(_("Opening file...")));
223 slotStatusMsg(i18n(_("Ready.")));
226 void KInterface::slotFileQuit()
228 slotStatusMsg(i18n(_("Exiting...")));
229 p_intf->p_vlc->b_die = VLC_TRUE;
230 slotStatusMsg(i18n(_("Ready.")));
233 void KInterface::slotViewToolBar()
235 slotStatusMsg(i18n(_("Toggling toolbar...")));
236 ///////////////////////////////////////////////////////////////////
237 // turn Toolbar on or off
238 if(!viewToolBar->isChecked())
240 toolBar("mainToolBar")->hide();
244 toolBar("mainToolBar")->show();
247 slotStatusMsg(i18n(_("Ready.")));
250 void KInterface::slotViewStatusBar()
252 slotStatusMsg(i18n(_("Toggle the status bar...")));
253 ///////////////////////////////////////////////////////////////////
254 //turn Statusbar on or off
255 if(!viewStatusBar->isChecked())
264 slotStatusMsg(i18n(_("Ready.")));
267 void KInterface::slotShowPreferences()
270 KPreferences(this->p_intf, "main", this, "preferences");
273 void KInterface::slotStatusMsg(const QString &text)
275 ///////////////////////////////////////////////////////////////////
276 // change status message permanently
277 statusBar()->clear();
278 statusBar()->changeItem(text, ID_STATUS_MSG);
281 void KInterface::slotManage()
283 p_messagesWindow->update();
284 // p_intf->p_sys->p_app->processEvents();
285 vlc_mutex_lock( &p_intf->change_lock );
287 /* Update the input */
288 if( p_intf->p_sys->p_input == NULL )
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 )
294 languages->setEnabled( true );
295 subtitles->setEnabled( true );
296 info->setEnabled( true );
300 else if( p_intf->p_sys->p_input->b_dead )
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 );
309 /* If the "display popup" flag has changed */
310 if( p_intf->b_menu_change )
312 fTitleMenu->popup( ( QCursor::pos() ) );
313 p_intf->b_menu_change = 0;
316 if( p_intf->p_sys->p_input )
318 input_thread_t *p_input = p_intf->p_sys->p_input;
320 vlc_mutex_lock( &p_input->stream.stream_lock );
321 if( !p_input->b_die )
323 /* New input or stream map change */
324 if( p_input->stream.b_changed )
326 // E_(GtkModeManage)( p_intf );
327 //GtkSetupMenus( p_intf );
328 slotUpdateLanguages();
330 p_intf->p_sys->b_playing = 1;
331 p_input->stream.b_changed = 0;
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 )
341 vlc_mutex_lock( &p_input->stream.stream_lock );
346 // if( p_intf->p_sys->i_part !=
347 // p_input->stream.p_selected_area->i_part )
349 // p_intf->p_sys->b_chapter_update = 1;
350 //GtkSetupMenus( p_intf );
353 vlc_mutex_unlock( &p_input->stream.stream_lock );
357 else if( p_intf->p_sys->b_playing && !p_intf->b_die )
359 //E_(GtkModeManage)( p_intf );
360 p_intf->p_sys->b_playing = 0;
365 p_intf->p_sys->p_app->quit();
368 vlc_mutex_unlock( &p_intf->change_lock );
373 void KInterface::slotSliderMoved( int position )
375 if( p_intf->p_sys->p_input )
377 // XXX is this locking really useful ?
378 vlc_mutex_lock( &p_intf->change_lock );
380 off_t i_seek = ( position * p_intf->p_sys->p_input->stream.p_selected_area->i_size ) / 10000;
381 input_Seek( p_intf->p_sys->p_input, i_seek, INPUT_SEEK_SET );
383 vlc_mutex_unlock( &p_intf->change_lock );
387 void KInterface::slotUpdateLanguages()
390 es_descriptor_t * p_spu_es;
391 es_descriptor_t * p_audio_es;
392 /* look for selected ES */
396 for( unsigned int i = 0 ;
397 i < p_intf->p_sys->p_input->stream.i_selected_es_number ;
401 if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat
404 p_audio_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
407 if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
409 p_spu_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
412 languages->setEnabled( false );
413 subtitles->setEnabled( false );
414 languageCollection->clear();
415 subtitleCollection->clear();
416 languages->popupMenu()->clear();
417 subtitles->popupMenu()->clear();
419 /* find audio root menu */
420 languageMenus( languages, p_audio_es, AUDIO_ES );
422 /* sub picture menus */
423 /* find spu root menu */
424 languageMenus( subtitles, p_spu_es, SPU_ES );
430 * called with stream lock
432 void KInterface::languageMenus(KActionMenu *root, es_descriptor_t *p_es,
436 if ( i_cat != AUDIO_ES )
438 KLanguageMenuAction *p_item =
439 new KLanguageMenuAction( p_intf, _( "Off" ), 0, this );
440 subtitleCollection->insert( p_item );
441 root->insert( p_item );
442 root->insert( new KActionSeparator( this ) );
443 p_item->setExclusiveGroup( QString().sprintf( "%d", i_cat ) );
444 p_item->setChecked( p_es == 0 );
447 #define ES p_intf->p_sys->p_input->stream.pp_es[i]
448 /* create a set of language buttons and append them to the container */
449 for( unsigned int i = 0 ;
450 i < p_intf->p_sys->p_input->stream.i_es_number ;
453 if( ( ES->i_cat == i_cat ) &&
456 p_intf->p_sys->p_input->stream.p_selected_program ) )
459 QString name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc;
462 name.sprintf( "Language %d", i_item );
464 KLanguageMenuAction *p_item;
465 if ( i_cat == AUDIO_ES )
467 p_item = new KLanguageMenuAction( p_intf, name, ES,
469 languageCollection->insert(p_item);
473 p_item = new KLanguageMenuAction( p_intf, name, ES,
475 subtitleCollection->insert(p_item);
477 p_item->setExclusiveGroup( QString().sprintf( "%d", i_cat ) );
478 root->insert( p_item );
480 if( p_es == p_intf->p_sys->p_input->stream.pp_es[i] )
482 /* don't lose p_item when we append into menu */
483 //p_item_active = p_item;
484 p_item->setChecked( true );
486 connect( p_item, SIGNAL( toggled( bool, es_descriptor_t * ) ),
487 this, SLOT( slotSetLanguage( bool, es_descriptor_t * ) ));
492 root->setEnabled( true );
496 void KInterface::slotSetLanguage( bool on, es_descriptor_t *p_es )
498 input_ToggleES( p_intf->p_sys->p_input, p_es, on );
501 void KInterface::slotSliderChanged( int position )
503 if( p_intf->p_sys->p_input != NULL )
505 char psz_time[ MSTRTIME_MAX_SIZE ];
507 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
509 #define p_area p_intf->p_sys->p_input->stream.p_selected_area
510 statusBar()->changeItem( input_OffsetToTime( p_intf->p_sys->p_input, psz_time, ( p_area->i_size * position ) / 10000 ), ID_DATE );
513 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
517 void KInterface::slotOpenDisk()
519 playlist_t *p_playlist;
520 int r = fDiskDialog->exec();
525 source += fDiskDialog->type();
527 source += fDiskDialog->device();
530 source += fDiskDialog->title();
532 source += fDiskDialog->chapter();
534 p_playlist = (playlist_t *)
535 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
538 // add it to playlist
539 playlist_Add( p_playlist, source.latin1(), source.latin1(),
540 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
541 vlc_object_release( p_playlist );
546 void KInterface::slotOpenStream()
548 playlist_t *p_playlist;
549 int r = fNetDialog->exec();
554 source += fNetDialog->protocol();
556 source += fNetDialog->server();
558 source += QString().setNum( fNetDialog->port() );
560 p_playlist = (playlist_t *)
561 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
564 // add it to playlist
565 playlist_Add( p_playlist, source.latin1(), source.latin1(),
566 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
567 vlc_object_release( p_playlist );
572 void KInterface::slotPlay()
574 if( p_intf->p_sys->p_input )
576 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
580 void KInterface::slotPause()
582 if ( p_intf->p_sys->p_input )
584 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
588 void KInterface::slotStop()
590 playlist_t *p_playlist = (playlist_t *)
591 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
594 playlist_Stop( p_playlist );
595 vlc_object_release( p_playlist );
599 void KInterface::slotBackward()
601 msg_Err( p_intf, "KInterface::slotBackward() - Unimplemented" );
604 void KInterface::slotPrev()
606 playlist_t *p_playlist = (playlist_t *)
607 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
610 playlist_Prev( p_playlist );
611 vlc_object_release( p_playlist );
615 void KInterface::slotNext()
617 playlist_t *p_playlist = (playlist_t *)
618 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
621 playlist_Next( p_playlist );
622 vlc_object_release( p_playlist );
626 void KInterface::slotSlow()
628 if( p_intf->p_sys->p_input != NULL )
630 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
634 void KInterface::slotFast()
636 if( p_intf->p_sys->p_input != NULL )
638 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
642 void KInterface::dragEnterEvent( QDragEnterEvent *event )
644 event->accept( QUriDrag::canDecode( event ) );
647 void KInterface::dropEvent( QDropEvent *event )
651 playlist_t *p_playlist = (playlist_t *)
652 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
653 if( p_playlist == NULL )
658 if ( KURLDrag::decode( event, urlList ) )
660 for ( KURL::List::ConstIterator i = urlList.begin(); i != urlList.end(); i++ )
662 // XXX add a private function to add a KURL with checking
663 // actually a whole class for core abstraction would be neat
664 if( !(*i).isEmpty() )
666 fileOpenRecent->addURL( *i );
667 playlist_Add( p_playlist, (*i).path(), (*i).path(),
668 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
673 vlc_object_release( p_playlist );