/*************************************************************************** interface.cpp - description ------------------- begin : Sun Mar 25 2001 copyright : (C) 2001 by andres email : dae@chez.com ***************************************************************************/ #include "disc.h" #include "info.h" #include "interface.h" #include "net.h" #include "menu.h" #include "slider.h" #include "preferences.h" #include "languagemenu.h" #include #include #include #include #include #include #include #include #include #include #include #include #define ID_STATUS_MSG 1 #define ID_DATE 2 #define ID_STREAM_SOURCE 3 KInterface::KInterface( intf_thread_t *p_intf, QWidget *parent, const char *name ) : KMainWindow(parent,name) { setAcceptDrops(true); this->p_intf = p_intf; p_messagesWindow = new KMessagesWindow( p_intf, p_intf->p_sys->p_msg ); fDiskDialog = new KDiskDialog( this ); fNetDialog = new KNetDialog( this ); fTitleMenu = new KTitleMenu( p_intf, this ); fSlider = new KVLCSlider( QSlider::Horizontal, this ); fSlider->setMaxValue(10000); connect( fSlider, SIGNAL( userChanged( int ) ), this, SLOT( slotSliderMoved( int ) ) ); connect( fSlider, SIGNAL( valueChanged( int ) ), this, SLOT( slotSliderChanged( int ) ) ); connect( fSlider, SIGNAL( sliderMoved( int ) ), this, SLOT( slotSliderChanged( int ) ) ); setCentralWidget(fSlider); fTimer = new QTimer( this ); connect( fTimer, SIGNAL( timeout() ), this, SLOT( slotManage() ) ); resize( 400, 30 ); /////////////////////////////////////////////////////////////////// // call inits to invoke all other construction parts // XXX could we move this up ? initStatusBar(); initActions(); // add certain calls to the popup menu fileOpen->plug( fTitleMenu ); fileOpenRecent->plug( fTitleMenu ); diskOpen->plug( fTitleMenu ); streamOpen->plug( fTitleMenu ); play->plug( fTitleMenu ); pause->plug( fTitleMenu ); slow->plug( fTitleMenu ); fast->plug( fTitleMenu ); fileQuit->plug( fTitleMenu ); fTimer->start( 0, FALSE ); } KInterface::~KInterface() { ; } void KInterface::initActions() { languages = new KActionMenu( _( "Languages" ), actionCollection(), "language" ); languages->setEnabled( false ); languageCollection = new KActionCollection( this ); subtitleCollection = new KActionCollection( this ); subtitles = new KActionMenu( _( "Subtitles" ), actionCollection(), "subtitles" ); subtitles->setEnabled( false ); fileOpen = KStdAction::open(this, SLOT(slotFileOpen()), actionCollection()); fileOpenRecent = KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)), actionCollection()); preferences = KStdAction::preferences(this, SLOT(slotShowPreferences()), actionCollection()); fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection()); viewToolBar = KStdAction::showToolbar(this, SLOT(slotViewToolBar()), actionCollection()); viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection()); diskOpen = new KAction( i18n( "Open &Disk" ), 0, 0, this, SLOT( slotOpenDisk() ), actionCollection(), "open_disk" ); streamOpen = new KAction( i18n( "Open &Stream" ), 0, 0, this, SLOT( slotOpenStream() ), actionCollection(), "open_stream" ); backward = new KAction( i18n( "&Backward" ), 0, 0, this, SLOT( slotBackward() ), actionCollection(), "backward" ); stop = new KAction( i18n( "&Stop" ), 0, 0, this, SLOT( slotStop() ), actionCollection(), "stop" ); play = new KAction( i18n( "&Play" ), 0, 0, this, SLOT( slotPlay() ), actionCollection(), "play" ); pause = new KAction( i18n( "P&ause" ), 0, 0, this, SLOT( slotPause() ), actionCollection(), "pause" ); slow = new KAction( i18n( "&Slow" ), 0, 0, this, SLOT( slotSlow() ), actionCollection(), "slow" ); fast = new KAction( i18n( "Fas&t" ), 0, 0, this, SLOT( slotFast() ), actionCollection(), "fast" ); prev = new KAction( i18n( "Prev" ), 0, 0, this, SLOT( slotPrev() ), actionCollection(), "prev" ); next = new KAction( i18n( "Next" ), 0, 0, this, SLOT( slotNext() ), actionCollection(), "next" ); messages = new KAction( _( "Messages..." ), 0, 0, this, SLOT( slotShowMessages() ), actionCollection(), "view_messages"); info = new KAction( _( "Stream info..." ), 0, 0, this, SLOT( slotShowInfo() ), actionCollection(), "view_stream_info"); info->setEnabled( false ); program = new KActionMenu( _( "Program" ), actionCollection(), "program" ); program->setEnabled( false ); title = new KActionMenu( _( "Title" ), actionCollection(), "title" ); title->setEnabled( false ); chapter = new KActionMenu( _( "Chapter" ), actionCollection(), "chapter" ); chapter->setEnabled( false ); fileOpen->setStatusText(i18n("Opens an existing document")); fileOpenRecent->setStatusText(i18n("Opens a recently used file")); fileQuit->setStatusText(i18n("Quits the application")); viewToolBar->setStatusText(i18n("Enables/disables the toolbar")); viewStatusBar->setStatusText(i18n("Enables/disables the statusbar")); diskOpen->setStatusText( i18n( "Opens a disk") ); streamOpen->setStatusText( i18n( "Opens a network stream" ) ); backward->setStatusText( i18n( "Backward" ) ); stop->setStatusText( i18n( "Stops playback" ) ); play->setStatusText( i18n( "Starts playback" ) ); pause->setStatusText( i18n( "Pauses playback" ) ); slow->setStatusText( i18n( "Slow" ) ); fast->setStatusText( i18n( "Fast" ) ); prev->setStatusText( i18n( "Prev" ) ); next->setStatusText( i18n( "Next" ) ); // use the absolute path to your ktestui.rc file for testing purpose in createGUI(); char *uifile = config_GetPsz( p_intf, "kdeuirc" ); createGUI( uifile ); // createGUI( "./modules/gui/kde/ui.rc" ); } void KInterface::initStatusBar() { /////////////////////////////////////////////////////////////////// // STATUSBAR // TODO: add your own items you need for displaying current application status. statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG, 1, false); statusBar()->setItemAlignment( ID_STATUS_MSG, AlignLeft | AlignVCenter ); statusBar()->insertItem( "0:00:00", ID_DATE, 0, true ); } ///////////////////////////////////////////////////////////////////// // SLOT IMPLEMENTATION ///////////////////////////////////////////////////////////////////// void KInterface::slotShowMessages() { p_messagesWindow->show(); } void KInterface::slotShowInfo() { if ( p_intf->p_sys->p_input ) { new KInfoWindow(p_intf, p_intf->p_sys->p_input); } } void KInterface::slotFileOpen() { playlist_t *p_playlist; slotStatusMsg( i18n( "Opening file..." ) ); KURL url=KFileDialog::getOpenURL( QString::null, i18n( "*|All files" ), this, i18n( "Open File..." ) ); if( !url.isEmpty() ) { p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) { fileOpenRecent->addURL( url ); playlist_Add( p_playlist, url.path(), PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END ); vlc_object_release( p_playlist ); } } slotStatusMsg( i18n( "Ready." ) ); } void KInterface::slotFileOpenRecent(const KURL& url) { slotStatusMsg(i18n("Opening file...")); slotStatusMsg(i18n("Ready.")); } void KInterface::slotFileQuit() { slotStatusMsg(i18n("Exiting...")); p_intf->p_vlc->b_die = VLC_TRUE; slotStatusMsg(i18n("Ready.")); } void KInterface::slotViewToolBar() { slotStatusMsg(i18n("Toggling toolbar...")); /////////////////////////////////////////////////////////////////// // turn Toolbar on or off if(!viewToolBar->isChecked()) { toolBar("mainToolBar")->hide(); } else { toolBar("mainToolBar")->show(); } slotStatusMsg(i18n("Ready.")); } void KInterface::slotViewStatusBar() { slotStatusMsg(i18n("Toggle the statusbar...")); /////////////////////////////////////////////////////////////////// //turn Statusbar on or off if(!viewStatusBar->isChecked()) { statusBar()->hide(); } else { statusBar()->show(); } slotStatusMsg(i18n("Ready.")); } void KInterface::slotShowPreferences() { // Do something KPreferences(this->p_intf, "main", this, "preferences"); } void KInterface::slotStatusMsg(const QString &text) { /////////////////////////////////////////////////////////////////// // change status message permanently statusBar()->clear(); statusBar()->changeItem(text, ID_STATUS_MSG); } void KInterface::slotManage() { p_messagesWindow->update(); // p_intf->p_sys->p_app->processEvents(); vlc_mutex_lock( &p_intf->change_lock ); /* Update the input */ if( p_intf->p_sys->p_input == NULL ) { p_intf->p_sys->p_input = (input_thread_t *) vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); if ( p_intf->p_sys->p_input ) { languages->setEnabled( true ); subtitles->setEnabled( true ); info->setEnabled( true ); } } else if( p_intf->p_sys->p_input->b_dead ) { vlc_object_release( p_intf->p_sys->p_input ); p_intf->p_sys->p_input = NULL; languages->setEnabled( false ); subtitles->setEnabled( false ); info->setEnabled( false ); } /* If the "display popup" flag has changed */ if( p_intf->b_menu_change ) { fTitleMenu->popup( ( QCursor::pos() ) ); p_intf->b_menu_change = 0; } if( p_intf->p_sys->p_input ) { input_thread_t *p_input = p_intf->p_sys->p_input; vlc_mutex_lock( &p_input->stream.stream_lock ); if( !p_input->b_die ) { /* New input or stream map change */ if( p_input->stream.b_changed ) { // E_(GtkModeManage)( p_intf ); //GtkSetupMenus( p_intf ); slotUpdateLanguages(); p_intf->p_sys->b_playing = 1; p_input->stream.b_changed = 0; } /* Manage the slider. fSlider->setValue triggers * slotSliderChanged which needs to grab the stream lock*/ #define p_area p_input->stream.p_selected_area if( p_area->i_size ) { vlc_mutex_unlock( &p_input->stream.stream_lock ); fSlider->setValue( ( 10000 * p_area->i_tell ) / p_area->i_size ); vlc_mutex_lock( &p_input->stream.stream_lock ); } #undef p_area // if( p_intf->p_sys->i_part != // p_input->stream.p_selected_area->i_part ) //{ // p_intf->p_sys->b_chapter_update = 1; //GtkSetupMenus( p_intf ); //} } vlc_mutex_unlock( &p_input->stream.stream_lock ); } else if( p_intf->p_sys->b_playing && !p_intf->b_die ) { //E_(GtkModeManage)( p_intf ); p_intf->p_sys->b_playing = 0; } if( p_intf->b_die ) { p_intf->p_sys->p_app->quit(); } vlc_mutex_unlock( &p_intf->change_lock ); msleep( 100 ); } void KInterface::slotSliderMoved( int position ) { if( p_intf->p_sys->p_input ) { // XXX is this locking really useful ? vlc_mutex_lock( &p_intf->change_lock ); off_t i_seek = ( position * p_intf->p_sys->p_input->stream.p_selected_area->i_size ) / 10000; input_Seek( p_intf->p_sys->p_input, i_seek, INPUT_SEEK_SET ); vlc_mutex_unlock( &p_intf->change_lock ); } } void KInterface::slotUpdateLanguages() { es_descriptor_t * p_spu_es; es_descriptor_t * p_audio_es; /* look for selected ES */ p_audio_es = NULL; p_spu_es = NULL; for( unsigned int i = 0 ; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ ) { if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES ) { p_audio_es = p_intf->p_sys->p_input->stream.pp_selected_es[i]; } if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES ) { p_spu_es = p_intf->p_sys->p_input->stream.pp_selected_es[i]; } } languages->setEnabled( false ); subtitles->setEnabled( false ); languageCollection->clear(); subtitleCollection->clear(); languages->popupMenu()->clear(); subtitles->popupMenu()->clear(); /* audio menus */ /* find audio root menu */ languageMenus( languages, p_audio_es, AUDIO_ES ); /* sub picture menus */ /* find spu root menu */ languageMenus( subtitles, p_spu_es, SPU_ES ); } /* * called with stream lock */ void KInterface::languageMenus(KActionMenu *root, es_descriptor_t *p_es, int i_cat) { int i_item = 0; if ( i_cat != AUDIO_ES ) { KLanguageMenuAction *p_item = new KLanguageMenuAction( p_intf, _( "Off" ), 0, this ); subtitleCollection->insert( p_item ); root->insert( p_item ); root->insert( new KActionSeparator( this ) ); p_item->setExclusiveGroup( QString().sprintf( "%d", i_cat ) ); p_item->setChecked( p_es == 0 ); } #define ES p_intf->p_sys->p_input->stream.pp_es[i] /* create a set of language buttons and append them to the container */ for( unsigned int i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ ) { if( ( ES->i_cat == i_cat ) && ( !ES->p_pgrm || ES->p_pgrm == p_intf->p_sys->p_input->stream.p_selected_program ) ) { i_item++; QString name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc; if( name.isEmpty() ) { name.sprintf( "Language %d", i_item ); } KLanguageMenuAction *p_item; if ( i_cat == AUDIO_ES ) { p_item = new KLanguageMenuAction( p_intf, name, ES, this ); languageCollection->insert(p_item); } else { p_item = new KLanguageMenuAction( p_intf, name, ES, this ); subtitleCollection->insert(p_item); } p_item->setExclusiveGroup( QString().sprintf( "%d", i_cat ) ); root->insert( p_item ); if( p_es == p_intf->p_sys->p_input->stream.pp_es[i] ) { /* don't lose p_item when we append into menu */ //p_item_active = p_item; p_item->setChecked( true ); } connect( p_item, SIGNAL( toggled( bool, es_descriptor_t * ) ), this, SLOT( slotSetLanguage( bool, es_descriptor_t * ) )); } } root->setEnabled( true ); } void KInterface::slotSetLanguage( bool on, es_descriptor_t *p_es ) { input_ToggleES( p_intf->p_sys->p_input, p_es, on ); } void KInterface::slotSliderChanged( int position ) { if( p_intf->p_sys->p_input != NULL ) { char psz_time[ OFFSETTOTIME_MAX_SIZE ]; vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock ); #define p_area p_intf->p_sys->p_input->stream.p_selected_area statusBar()->changeItem( input_OffsetToTime( p_intf->p_sys->p_input, psz_time, ( p_area->i_size * position ) / 10000 ), ID_DATE ); #undef p_area vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock ); } } void KInterface::slotOpenDisk() { playlist_t *p_playlist; int r = fDiskDialog->exec(); if ( r ) { // Build source name QString source; source += fDiskDialog->type(); source += ':'; source += fDiskDialog->device(); source += '@'; source += fDiskDialog->title(); source += ','; source += fDiskDialog->chapter(); p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) { // add it to playlist playlist_Add( p_playlist, source.latin1(), PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END ); vlc_object_release( p_playlist ); } } } void KInterface::slotOpenStream() { playlist_t *p_playlist; int r = fNetDialog->exec(); if ( r ) { // Build source name QString source; source += fNetDialog->protocol(); source += "://"; source += fNetDialog->server(); source += ":"; source += QString().setNum( fNetDialog->port() ); p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) { // add it to playlist playlist_Add( p_playlist, source.latin1(), PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END ); vlc_object_release( p_playlist ); } } } void KInterface::slotPlay() { if( p_intf->p_sys->p_input ) { input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY ); } } void KInterface::slotPause() { if ( p_intf->p_sys->p_input ) { input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE ); } } void KInterface::slotStop() { playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) { playlist_Stop( p_playlist ); vlc_object_release( p_playlist ); } } void KInterface::slotBackward() { msg_Err( p_intf, "KInterface::slotBackward() - Unimplemented" ); } void KInterface::slotPrev() { playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) { playlist_Prev( p_playlist ); vlc_object_release( p_playlist ); } } void KInterface::slotNext() { playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) { playlist_Next( p_playlist ); vlc_object_release( p_playlist ); } } void KInterface::slotSlow() { if( p_intf->p_sys->p_input != NULL ) { input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER ); } } void KInterface::slotFast() { if( p_intf->p_sys->p_input != NULL ) { input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER ); } } void KInterface::dragEnterEvent( QDragEnterEvent *event ) { event->accept( QUriDrag::canDecode( event ) ); } void KInterface::dropEvent( QDropEvent *event ) { KURL::List urlList; playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist == NULL ) { return; } if ( KURLDrag::decode( event, urlList ) ) { for ( KURL::List::ConstIterator i = urlList.begin(); i != urlList.end(); i++ ) { // XXX add a private function to add a KURL with checking // actually a whole class for core abstraction would be neat if( !(*i).isEmpty() ) { fileOpenRecent->addURL( *i ); playlist_Add( p_playlist, (*i).path(), PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END ); } } } vlc_object_release( p_playlist ); }