1 /*****************************************************************************
2 * main_inteface.cpp : Main interface
3 *****************************************************************************
4 * Copyright (C) 2006-2007 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Jean-Baptiste Kempf <jb@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
29 #include <QApplication>
30 #include <QSignalMapper>
31 #include <QFileDialog>
33 #include <vlc_common.h>
35 #include "dialogs_provider.hpp"
36 #include "main_interface.hpp"
38 #include <vlc_intf_strings.h>
39 #include "input_manager.hpp"
42 #include "dialogs/playlist.hpp"
43 #include "dialogs/bookmarks.hpp"
44 #include "dialogs/preferences.hpp"
45 #include "dialogs/mediainfo.hpp"
46 #include "dialogs/messages.hpp"
47 #include "dialogs/extended.hpp"
48 #include "dialogs/vlm.hpp"
49 #include "dialogs/sout.hpp"
50 #include "dialogs/open.hpp"
51 #include "dialogs/help.hpp"
52 #include "dialogs/gototime.hpp"
53 #include "dialogs/podcast_configuration.hpp"
55 DialogsProvider
* DialogsProvider::instance
= NULL
;
57 DialogsProvider::DialogsProvider( intf_thread_t
*_p_intf
) :
58 QObject( NULL
), p_intf( _p_intf
)
60 fixed_timer
= new QTimer( this );
61 fixed_timer
->start( 150 /* milliseconds */ );
63 menusMapper
= new QSignalMapper();
64 CONNECT( menusMapper
, mapped(QObject
*), this, menuAction( QObject
*) );
66 menusUpdateMapper
= new QSignalMapper();
67 CONNECT( menusUpdateMapper
, mapped(QObject
*),
68 this, menuUpdateAction( QObject
*) );
70 SDMapper
= new QSignalMapper();
71 CONNECT( SDMapper
, mapped (QString
), this, SDMenuAction( QString
) );
74 DialogsProvider::~DialogsProvider()
76 msg_Dbg( p_intf
, "Destroying the Dialog Provider" );
77 PlaylistDialog::killInstance();
78 MediaInfoDialog::killInstance();
79 MessagesDialog::killInstance();
80 ExtendedDialog::killInstance();
81 BookmarksDialog::killInstance();
82 HelpDialog::killInstance();
84 UpdateDialog::killInstance();
90 void DialogsProvider::quit()
92 vlc_object_kill( p_intf
->p_libvlc
);
93 QApplication::closeAllWindows();
97 void DialogsProvider::customEvent( QEvent
*event
)
99 if( event
->type() == DialogEvent_Type
)
101 DialogEvent
*de
= static_cast<DialogEvent
*>(event
);
102 switch( de
->i_dialog
)
104 case INTF_DIALOG_FILE_SIMPLE
:
105 case INTF_DIALOG_FILE
:
107 case INTF_DIALOG_FILE_GENERIC
:
108 openFileGenericDialog( de
->p_arg
); break;
109 case INTF_DIALOG_DISC
:
110 openDiscDialog(); break;
111 case INTF_DIALOG_NET
:
112 openNetDialog(); break;
113 case INTF_DIALOG_SAT
:
114 case INTF_DIALOG_CAPTURE
:
115 openCaptureDialog(); break;
116 case INTF_DIALOG_DIRECTORY
:
117 PLAppendDir(); break;
118 case INTF_DIALOG_PLAYLIST
:
119 playlistDialog(); break;
120 case INTF_DIALOG_MESSAGES
:
121 messagesDialog(); break;
122 case INTF_DIALOG_FILEINFO
:
123 mediaInfoDialog(); break;
124 case INTF_DIALOG_PREFS
:
125 prefsDialog(); break;
126 case INTF_DIALOG_BOOKMARKS
:
127 bookmarksDialog(); break;
128 case INTF_DIALOG_EXTENDED
:
129 extendedDialog(); break;
131 case INTF_DIALOG_VLM
:
134 case INTF_DIALOG_INTERACTION
:
135 doInteraction( de
->p_arg
); break;
136 case INTF_DIALOG_POPUPMENU
:
137 QVLCMenu::PopupMenu( p_intf
, (de
->i_arg
!= 0) ); break;
138 case INTF_DIALOG_AUDIOPOPUPMENU
:
139 QVLCMenu::AudioPopupMenu( p_intf
); break;
140 case INTF_DIALOG_VIDEOPOPUPMENU
:
141 QVLCMenu::VideoPopupMenu( p_intf
); break;
142 case INTF_DIALOG_MISCPOPUPMENU
:
143 QVLCMenu::MiscPopupMenu( p_intf
); break;
144 case INTF_DIALOG_WIZARD
:
145 case INTF_DIALOG_STREAMWIZARD
:
146 openThenStreamingDialogs(); break;
148 case INTF_DIALOG_UPDATEVLC
:
149 updateDialog(); break;
151 case INTF_DIALOG_EXIT
:
154 msg_Warn( p_intf
, "unimplemented dialog" );
159 /****************************************************************************
160 * Individual simple dialogs
161 ****************************************************************************/
162 void DialogsProvider::playlistDialog()
164 PlaylistDialog::getInstance( p_intf
)->toggleVisible();
167 void DialogsProvider::prefsDialog()
169 PrefsDialog::getInstance( p_intf
)->toggleVisible();
172 void DialogsProvider::extendedDialog()
174 ExtendedDialog::getInstance( p_intf
)->toggleVisible();
177 void DialogsProvider::messagesDialog()
179 MessagesDialog::getInstance( p_intf
)->toggleVisible();
182 void DialogsProvider::gotoTimeDialog()
184 GotoTimeDialog::getInstance( p_intf
)->toggleVisible();
188 void DialogsProvider::vlmDialog()
190 VLMDialog::getInstance( p_intf
)->toggleVisible();
194 void DialogsProvider::helpDialog()
196 HelpDialog::getInstance( p_intf
)->toggleVisible();
200 void DialogsProvider::updateDialog()
202 UpdateDialog::getInstance( p_intf
)->toggleVisible();
206 void DialogsProvider::aboutDialog()
208 AboutDialog::getInstance( p_intf
)->toggleVisible();
211 void DialogsProvider::mediaInfoDialog()
213 MediaInfoDialog::getInstance( p_intf
)->toggleVisible();
216 void DialogsProvider::mediaCodecDialog()
218 MediaInfoDialog::getInstance( p_intf
)->showTab( 2 );
221 void DialogsProvider::bookmarksDialog()
223 BookmarksDialog::getInstance( p_intf
)->toggleVisible();
226 void DialogsProvider::podcastConfigureDialog()
228 PodcastConfigDialog::getInstance( p_intf
)->toggleVisible();
232 /****************************************************************************
233 * All the open/add stuff
234 * Open Dialog first - Simple Open then
235 ****************************************************************************/
237 void DialogsProvider::openDialog( int i_tab
)
239 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
)->showTab( i_tab
);
241 void DialogsProvider::openDialog()
243 openDialog( OPEN_FILE_TAB
);
245 void DialogsProvider::openFileGenericDialog( intf_dialog_args_t
*p_arg
)
249 msg_Dbg( p_intf
, "openFileGenericDialog() called with NULL arg" );
253 QString extensions
= qfu( p_arg
->psz_extensions
);
254 while ( ( i
= extensions
.indexOf( "|", i
) ) != -1 )
256 if( ( extensions
.count( "|" ) % 2 ) == 0 )
257 extensions
.replace( i
, 1, ");;" );
259 extensions
.replace( i
, 1, "(" );
261 extensions
.replace(QString(";*"), QString(" *"));
262 extensions
.append( ")" );
265 QString file
= QFileDialog::getSaveFileName( NULL
, p_arg
->psz_title
, qfu( p_intf
->p_sys
->psz_filepath
), extensions
);
266 if( !file
.isEmpty() )
268 p_arg
->i_results
= 1;
269 p_arg
->psz_results
= ( char ** )malloc( p_arg
->i_results
* sizeof( char * ) );
270 p_arg
->psz_results
[0] = strdup( qtu( file
) );
273 p_arg
->i_results
= 0;
277 QStringList files
= QFileDialog::getOpenFileNames( NULL
, p_arg
->psz_title
, qfu( p_intf
->p_sys
->psz_filepath
), extensions
);
278 p_arg
->i_results
= files
.count();
279 p_arg
->psz_results
= ( char ** )malloc( p_arg
->i_results
* sizeof( char * ) );
281 foreach( QString file
, files
)
282 p_arg
->psz_results
[i
++] = strdup( qtu( file
) );
284 if( p_arg
->pf_callback
)
285 p_arg
->pf_callback( p_arg
);
286 if( p_arg
->psz_results
)
288 for( i
= 0; i
< p_arg
->i_results
; i
++ )
289 free( p_arg
->psz_results
[i
] );
290 free( p_arg
->psz_results
);
292 free( p_arg
->psz_title
);
293 free( p_arg
->psz_extensions
);
296 void DialogsProvider::openFileDialog()
298 openDialog( OPEN_FILE_TAB
);
300 void DialogsProvider::openDiscDialog()
302 openDialog( OPEN_DISC_TAB
);
304 void DialogsProvider::openNetDialog()
306 openDialog( OPEN_NETWORK_TAB
);
308 void DialogsProvider::openCaptureDialog()
310 openDialog( OPEN_CAPTURE_TAB
);
313 /* Same as the open one, but force the enqueue */
314 void DialogsProvider::PLAppendDialog()
316 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
, false, OPEN_AND_ENQUEUE
)
317 ->showTab( OPEN_FILE_TAB
);
320 /* Unimplemmented yet - Usefull ? */
321 void DialogsProvider::MLAppendDialog()
326 * Not used anymore. Let the code until we are sure we don't want it
327 * Two opens make it confusing for the user.
329 QStringList
DialogsProvider::showSimpleOpen( QString help
,
333 QString fileTypes
= "";
334 if( filters
& EXT_FILTER_MEDIA
) {
335 ADD_FILTER_MEDIA( fileTypes
);
337 if( filters
& EXT_FILTER_VIDEO
) {
338 ADD_FILTER_VIDEO( fileTypes
);
340 if( filters
& EXT_FILTER_AUDIO
) {
341 ADD_FILTER_AUDIO( fileTypes
);
343 if( filters
& EXT_FILTER_PLAYLIST
) {
344 ADD_FILTER_PLAYLIST( fileTypes
);
346 if( filters
& EXT_FILTER_SUBTITLE
) {
347 ADD_FILTER_SUBTITLE( fileTypes
);
349 ADD_FILTER_ALL( fileTypes
);
350 fileTypes
.replace(QString(";*"), QString(" *"));
351 return QFileDialog::getOpenFileNames( NULL
,
352 help
.isNull() ? qfu(I_OP_SEL_FILES
) : help
,
353 path
.isNull() ? qfu( p_intf
->p_sys
->psz_filepath
) : path
,
359 * pl helps you to choose from playlist or media library,
360 * go to start or enqueue
362 void DialogsProvider::addFromSimple( bool pl
, bool go
)
364 QStringList files
= DialogsProvider::showSimpleOpen();
366 foreach( QString file
, files
)
368 const char * psz_utf8
= qtu( file
);
369 playlist_Add( THEPL
, psz_utf8
, NULL
,
370 go
? ( PLAYLIST_APPEND
| ( i
? 0 : PLAYLIST_GO
) |
371 ( i
? PLAYLIST_PREPARSE
: 0 ) )
372 : ( PLAYLIST_APPEND
| PLAYLIST_PREPARSE
),
374 pl
? true : false, false );
379 void DialogsProvider::simpleOpenDialog()
381 addFromSimple( true, true ); /* Playlist and Go */
384 void DialogsProvider::simplePLAppendDialog()
386 addFromSimple( true, false );
389 void DialogsProvider::simpleMLAppendDialog()
391 addFromSimple( false, false );
397 * pl helps you to choose from playlist or media library,
398 * go to start or enqueue
400 static void openDirectory( intf_thread_t
*p_intf
, bool pl
, bool go
)
402 QString dir
= QFileDialog::getExistingDirectory( 0, qtr("Open Directory") );
403 if (!dir
.isEmpty()) {
404 input_item_t
*p_input
= input_ItemNewExt( THEPL
,
405 qtu( "directory://" + dir
), NULL
,
408 /* FIXME: playlist_AddInput() can fail */
409 playlist_AddInput( THEPL
, p_input
,
410 go
? ( PLAYLIST_APPEND
| PLAYLIST_GO
) : PLAYLIST_APPEND
,
411 PLAYLIST_END
, pl
, pl_Unlocked
);
412 input_Read( THEPL
, p_input
, false );
413 vlc_gc_decref( p_input
);
417 void DialogsProvider::PLAppendDir()
419 openDirectory( p_intf
, true, false );
422 void DialogsProvider::MLAppendDir()
424 openDirectory( p_intf
, false , false );
430 void DialogsProvider::openAPlaylist()
432 QStringList files
= showSimpleOpen( qtr( "Open playlist file" ),
433 EXT_FILTER_PLAYLIST
);
434 foreach( QString file
, files
)
436 playlist_Import( THEPL
, qtu(file
) );
440 void DialogsProvider::saveAPlaylist()
442 QFileDialog
*qfd
= new QFileDialog( NULL
,
443 qtr( "Choose a filename to save playlist" ),
444 qfu( p_intf
->p_sys
->psz_filepath
),
445 qtr( "XSPF playlist (*.xspf);; " ) +
446 qtr( "M3U playlist (*.m3u);; Any (*.*) " ) );
447 qfd
->setFileMode( QFileDialog::AnyFile
);
448 qfd
->setAcceptMode( QFileDialog::AcceptSave
);
449 qfd
->setConfirmOverwrite( true );
451 if( qfd
->exec() == QDialog::Accepted
)
453 if( qfd
->selectedFiles().count() > 0 )
455 static const char psz_xspf
[] = "export-xspf",
456 psz_m3u
[] = "export-m3u";
457 const char *psz_module
;
459 QString file
= qfd
->selectedFiles().first();
460 QString filter
= qfd
->selectedFilter();
462 if( file
.contains( ".xsp" ) ||
463 ( filter
.contains( ".xspf" ) && !file
.contains( ".m3u" ) ) )
465 psz_module
= psz_xspf
;
466 if( !file
.contains( ".xsp" ) )
467 file
.append( ".xspf" );
471 psz_module
= psz_m3u
;
472 if( !file
.contains( ".m3u" ) )
473 file
.append( ".m3u" );
476 playlist_Export( THEPL
, qtu( file
), THEPL
->p_local_category
,
484 /****************************************************************************
486 ****************************************************************************/
488 void DialogsProvider::streamingDialog( QWidget
*parent
, QString mrl
,
489 bool b_transcode_only
)
491 SoutDialog
*s
= SoutDialog::getInstance( parent
, p_intf
, b_transcode_only
);
493 if( s
->exec() == QDialog::Accepted
)
495 msg_Dbg( p_intf
, "Sout mrl %s", qta( s
->getMrl() ) );
497 int i_len
= strlen( qtu( s
->getMrl() ) ) + 10;
498 char *psz_option
= (char*)malloc( i_len
);
499 snprintf( psz_option
, i_len
- 1, "%s", qtu( s
->getMrl() ) );
501 playlist_AddExt( THEPL
, qtu( mrl
), "Streaming",
502 PLAYLIST_APPEND
| PLAYLIST_GO
, PLAYLIST_END
,
503 -1, &psz_option
, 1, true, pl_Unlocked
);
507 void DialogsProvider::openThenStreamingDialogs()
509 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
, false, OPEN_AND_STREAM
)
510 ->showTab( OPEN_FILE_TAB
);
513 void DialogsProvider::openThenTranscodingDialogs()
515 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
, false, OPEN_AND_SAVE
)
516 ->showTab( OPEN_FILE_TAB
);
519 /****************************************************************************
520 * Menus / Interaction
521 ****************************************************************************/
523 void DialogsProvider::menuAction( QObject
*data
)
525 QVLCMenu::DoAction( p_intf
, data
);
528 void DialogsProvider::menuUpdateAction( QObject
*data
)
530 MenuFunc
* f
= qobject_cast
<MenuFunc
*>(data
);
534 void DialogsProvider::SDMenuAction( QString data
)
536 char *psz_sd
= strdup( qtu( data
) );
537 if( !playlist_IsServicesDiscoveryLoaded( THEPL
, psz_sd
) )
538 playlist_ServicesDiscoveryAdd( THEPL
, psz_sd
);
540 playlist_ServicesDiscoveryRemove( THEPL
, psz_sd
);
544 void DialogsProvider::doInteraction( intf_dialog_args_t
*p_arg
)
546 InteractionDialog
*qdialog
;
547 interaction_dialog_t
*p_dialog
= p_arg
->p_dialog
;
548 switch( p_dialog
->i_action
)
551 qdialog
= new InteractionDialog( p_intf
, p_dialog
);
552 p_dialog
->p_private
= (void*)qdialog
;
553 if( !(p_dialog
->i_status
== ANSWERED_DIALOG
) )
556 case INTERACT_UPDATE
:
557 qdialog
= (InteractionDialog
*)(p_dialog
->p_private
);
562 /* The INTERACT_NEW message was forgotten
563 so we must create the dialog and update it*/
564 qdialog
= new InteractionDialog( p_intf
, p_dialog
);
565 p_dialog
->p_private
= (void*)qdialog
;
566 if( !(p_dialog
->i_status
== ANSWERED_DIALOG
) )
573 qdialog
= (InteractionDialog
*)(p_dialog
->p_private
);
576 p_dialog
->i_status
= HIDDEN_DIALOG
;
578 case INTERACT_DESTROY
:
579 qdialog
= (InteractionDialog
*)(p_dialog
->p_private
);
580 if( !p_dialog
->i_flags
& DIALOG_NONBLOCKING_ERROR
)
582 p_dialog
->i_status
= DESTROYED_DIALOG
;
587 void DialogsProvider::loadSubtitlesFile()
589 input_thread_t
*p_input
= THEMIM
->getInput();
592 QString qsFile
= QFileDialog::getOpenFileName(
594 qtr( "Choose subtitles file" ),
596 qtr( "Subtitles files (*.cdg *.idx *.srt *.sub *.utf);;"
598 if( !input_AddSubtitles( p_input
, qtu( qsFile
), true ) )
599 msg_Warn( p_intf
, "unable to load subtitles file..." );