1 /*****************************************************************************
2 * dialogs_provider.cpp : Dialog Provider
3 *****************************************************************************
4 * Copyright (C) 2006-2008 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 <vlc_common.h>
30 #include <vlc_intf_strings.h>
33 #include "dialogs_provider.hpp"
34 #include "main_interface.hpp"
36 #include "input_manager.hpp"
37 #include "recents.hpp"
38 #include "util/qvlcapp.hpp"
41 #include "dialogs/playlist.hpp"
42 #include "dialogs/bookmarks.hpp"
43 #include "dialogs/preferences.hpp"
44 #include "dialogs/mediainfo.hpp"
45 #include "dialogs/messages.hpp"
46 #include "dialogs/extended.hpp"
47 #include "dialogs/vlm.hpp"
48 #include "dialogs/sout.hpp"
49 #include "dialogs/open.hpp"
50 #include "dialogs/help.hpp"
51 #include "dialogs/gototime.hpp"
52 #include "dialogs/podcast_configuration.hpp"
55 #include <QApplication>
56 #include <QSignalMapper>
57 #include <QFileDialog>
60 DialogsProvider
* DialogsProvider::instance
= NULL
;
62 DialogsProvider::DialogsProvider( intf_thread_t
*_p_intf
) :
63 QObject( NULL
), p_intf( _p_intf
)
67 /* Various signal mappers for the menus */
68 menusMapper
= new QSignalMapper();
69 CONNECT( menusMapper
, mapped(QObject
*), this, menuAction( QObject
*) );
71 menusUpdateMapper
= new QSignalMapper();
72 CONNECT( menusUpdateMapper
, mapped(QObject
*),
73 this, menuUpdateAction( QObject
*) );
75 SDMapper
= new QSignalMapper();
76 CONNECT( SDMapper
, mapped (QString
), this, SDMenuAction( QString
) );
79 DialogsProvider::~DialogsProvider()
81 msg_Dbg( p_intf
, "Destroying the Dialog Provider" );
82 PlaylistDialog::killInstance();
83 MediaInfoDialog::killInstance();
84 MessagesDialog::killInstance();
85 ExtendedDialog::killInstance();
86 BookmarksDialog::killInstance();
87 HelpDialog::killInstance();
89 UpdateDialog::killInstance();
93 delete menusUpdateMapper
;
97 void DialogsProvider::quit()
99 /* Stop the playlist */
100 playlist_Stop( THEPL
);
102 vlc_object_kill( p_intf
->p_libvlc
);
103 QApplication::closeAllWindows();
104 QApplication::quit();
107 void DialogsProvider::customEvent( QEvent
*event
)
109 if( event
->type() == (int)DialogEvent_Type
)
111 DialogEvent
*de
= static_cast<DialogEvent
*>(event
);
112 switch( de
->i_dialog
)
114 case INTF_DIALOG_FILE_SIMPLE
:
115 case INTF_DIALOG_FILE
:
117 case INTF_DIALOG_FILE_GENERIC
:
118 openFileGenericDialog( de
->p_arg
); break;
119 case INTF_DIALOG_DISC
:
120 openDiscDialog(); break;
121 case INTF_DIALOG_NET
:
122 openNetDialog(); break;
123 case INTF_DIALOG_SAT
:
124 case INTF_DIALOG_CAPTURE
:
125 openCaptureDialog(); break;
126 case INTF_DIALOG_DIRECTORY
:
127 PLAppendDir(); break;
128 case INTF_DIALOG_PLAYLIST
:
129 playlistDialog(); break;
130 case INTF_DIALOG_MESSAGES
:
131 messagesDialog(); break;
132 case INTF_DIALOG_FILEINFO
:
133 mediaInfoDialog(); break;
134 case INTF_DIALOG_PREFS
:
135 prefsDialog(); break;
136 case INTF_DIALOG_BOOKMARKS
:
137 bookmarksDialog(); break;
138 case INTF_DIALOG_EXTENDED
:
139 extendedDialog(); break;
141 case INTF_DIALOG_VLM
:
144 case INTF_DIALOG_INTERACTION
:
145 doInteraction( de
->p_arg
); break;
146 case INTF_DIALOG_POPUPMENU
:
147 QVLCMenu::PopupMenu( p_intf
, (de
->i_arg
!= 0) ); break;
148 case INTF_DIALOG_AUDIOPOPUPMENU
:
149 QVLCMenu::AudioPopupMenu( p_intf
); break;
150 case INTF_DIALOG_VIDEOPOPUPMENU
:
151 QVLCMenu::VideoPopupMenu( p_intf
); break;
152 case INTF_DIALOG_MISCPOPUPMENU
:
153 QVLCMenu::MiscPopupMenu( p_intf
); break;
154 case INTF_DIALOG_WIZARD
:
155 case INTF_DIALOG_STREAMWIZARD
:
156 openAndStreamingDialogs(); break;
158 case INTF_DIALOG_UPDATEVLC
:
159 updateDialog(); break;
161 case INTF_DIALOG_EXIT
:
164 msg_Warn( p_intf
, "unimplemented dialog" );
169 /****************************************************************************
170 * Individual simple dialogs
171 ****************************************************************************/
172 void DialogsProvider::playlistDialog()
174 PlaylistDialog::getInstance( p_intf
)->toggleVisible();
177 void DialogsProvider::prefsDialog()
179 PrefsDialog::getInstance( p_intf
)->toggleVisible();
182 void DialogsProvider::extendedDialog()
184 ExtendedDialog::getInstance( p_intf
)->toggleVisible();
187 void DialogsProvider::messagesDialog()
189 MessagesDialog::getInstance( p_intf
)->toggleVisible();
192 void DialogsProvider::gotoTimeDialog()
194 GotoTimeDialog::getInstance( p_intf
)->toggleVisible();
198 void DialogsProvider::vlmDialog()
200 VLMDialog::getInstance( p_intf
)->toggleVisible();
204 void DialogsProvider::helpDialog()
206 HelpDialog::getInstance( p_intf
)->toggleVisible();
210 void DialogsProvider::updateDialog()
212 UpdateDialog::getInstance( p_intf
)->toggleVisible();
216 void DialogsProvider::aboutDialog()
218 AboutDialog::getInstance( p_intf
)->toggleVisible();
221 void DialogsProvider::mediaInfoDialog()
223 MediaInfoDialog::getInstance( p_intf
)->toggleVisible();
226 void DialogsProvider::mediaCodecDialog()
228 MediaInfoDialog::getInstance( p_intf
)->showTab( 2 );
231 void DialogsProvider::bookmarksDialog()
233 BookmarksDialog::getInstance( p_intf
)->toggleVisible();
236 void DialogsProvider::podcastConfigureDialog()
238 PodcastConfigDialog::getInstance( p_intf
)->toggleVisible();
241 /* Generic open file */
242 void DialogsProvider::openFileGenericDialog( intf_dialog_args_t
*p_arg
)
246 msg_Warn( p_intf
, "openFileGenericDialog() called with NULL arg" );
250 /* Replace the extensions to a Qt format */
252 QString extensions
= qfu( p_arg
->psz_extensions
);
253 while ( ( i
= extensions
.indexOf( "|", i
) ) != -1 )
255 if( ( extensions
.count( "|" ) % 2 ) == 0 )
256 extensions
.replace( i
, 1, ");;" );
258 extensions
.replace( i
, 1, "(" );
260 extensions
.replace(QString(";*"), QString(" *"));
261 extensions
.append( ")" );
266 QString file
= QFileDialog::getSaveFileName( NULL
, p_arg
->psz_title
,
267 qfu( p_intf
->p_sys
->psz_filepath
), extensions
);
268 if( !file
.isEmpty() )
270 p_arg
->i_results
= 1;
271 p_arg
->psz_results
= (char **)malloc( p_arg
->i_results
* sizeof( char * ) );
272 p_arg
->psz_results
[0] = strdup( qtu( toNativeSepNoSlash( file
) ) );
275 p_arg
->i_results
= 0;
277 else /* non-save mode */
279 QStringList files
= QFileDialog::getOpenFileNames( NULL
,
280 p_arg
->psz_title
, qfu( p_intf
->p_sys
->psz_filepath
),
282 p_arg
->i_results
= files
.count();
283 p_arg
->psz_results
= (char **)malloc( p_arg
->i_results
* sizeof( char * ) );
285 foreach( QString file
, files
)
286 p_arg
->psz_results
[i
++] = strdup( qtu( toNativeSepNoSlash( file
) ) );
290 if( p_arg
->pf_callback
)
291 p_arg
->pf_callback( p_arg
);
293 /* Clean afterwards */
294 if( p_arg
->psz_results
)
296 for( i
= 0; i
< p_arg
->i_results
; i
++ )
297 free( p_arg
->psz_results
[i
] );
298 free( p_arg
->psz_results
);
300 free( p_arg
->psz_title
);
301 free( p_arg
->psz_extensions
);
304 /****************************************************************************
305 * All the open/add stuff
306 * Open Dialog first - Simple Open then
307 ****************************************************************************/
309 void DialogsProvider::openDialog( int i_tab
)
311 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
)->showTab( i_tab
);
313 void DialogsProvider::openDialog()
315 openDialog( OPEN_FILE_TAB
);
317 void DialogsProvider::openFileDialog()
319 openDialog( OPEN_FILE_TAB
);
321 void DialogsProvider::openDiscDialog()
323 openDialog( OPEN_DISC_TAB
);
325 void DialogsProvider::openNetDialog()
327 openDialog( OPEN_NETWORK_TAB
);
329 void DialogsProvider::openCaptureDialog()
331 openDialog( OPEN_CAPTURE_TAB
);
334 /* Same as the open one, but force the enqueue */
335 void DialogsProvider::PLAppendDialog()
337 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
, false,
338 OPEN_AND_ENQUEUE
)->showTab( OPEN_FILE_TAB
);
341 void DialogsProvider::MLAppendDialog()
343 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
, false,
344 OPEN_AND_ENQUEUE
, false, false )
345 ->showTab( OPEN_FILE_TAB
);
351 QStringList
DialogsProvider::showSimpleOpen( QString help
,
355 QString fileTypes
= "";
356 if( filters
& EXT_FILTER_MEDIA
) {
357 ADD_FILTER_MEDIA( fileTypes
);
359 if( filters
& EXT_FILTER_VIDEO
) {
360 ADD_FILTER_VIDEO( fileTypes
);
362 if( filters
& EXT_FILTER_AUDIO
) {
363 ADD_FILTER_AUDIO( fileTypes
);
365 if( filters
& EXT_FILTER_PLAYLIST
) {
366 ADD_FILTER_PLAYLIST( fileTypes
);
368 if( filters
& EXT_FILTER_SUBTITLE
) {
369 ADD_FILTER_SUBTITLE( fileTypes
);
371 ADD_FILTER_ALL( fileTypes
);
372 fileTypes
.replace(QString(";*"), QString(" *"));
374 return QFileDialog::getOpenFileNames( NULL
,
375 help
.isEmpty() ? qtr(I_OP_SEL_FILES
) : help
,
376 path
.isEmpty() ? qfu( p_intf
->p_sys
->psz_filepath
) : path
,
382 * pl helps you to choose from playlist or media library,
383 * go to start or enqueue
385 void DialogsProvider::addFromSimple( bool pl
, bool go
)
387 QStringList files
= DialogsProvider::showSimpleOpen();
389 foreach( QString file
, files
)
391 playlist_Add( THEPL
, qtu( toNativeSeparators( file
) ), NULL
,
392 go
? ( PLAYLIST_APPEND
| ( i
? 0 : PLAYLIST_GO
) |
393 ( i
? PLAYLIST_PREPARSE
: 0 ) )
394 : ( PLAYLIST_APPEND
| PLAYLIST_PREPARSE
),
396 pl
? true : false, false );
397 RecentsMRL::getInstance( p_intf
)->addRecent(
398 toNativeSeparators( file
) );
403 void DialogsProvider::simpleOpenDialog()
405 addFromSimple( true, true ); /* Playlist and Go */
408 void DialogsProvider::simplePLAppendDialog()
410 addFromSimple( true, false );
413 void DialogsProvider::simpleMLAppendDialog()
415 addFromSimple( false, false );
421 * pl helps you to choose from playlist or media library,
422 * go to start or enqueue
424 static void openDirectory( intf_thread_t
*p_intf
, bool pl
, bool go
)
426 QString dir
= QFileDialog::getExistingDirectory( NULL
, qtr("Open Directory") );
430 QString mrl
= dir
.endsWith( "VIDEO_TS", Qt::CaseInsensitive
) ?
431 "dvd://" : "directory://" + toNativeSeparators( dir
);
432 input_item_t
*p_input
= input_item_NewExt( THEPL
, qtu( mrl
),
435 /* FIXME: playlist_AddInput() can fail */
436 playlist_AddInput( THEPL
, p_input
,
437 go
? ( PLAYLIST_APPEND
| PLAYLIST_GO
) : PLAYLIST_APPEND
,
438 PLAYLIST_END
, pl
, pl_Unlocked
);
439 RecentsMRL::getInstance( p_intf
)->addRecent( mrl
);
441 input_Read( THEPL
, p_input
, true );
442 vlc_gc_decref( p_input
);
446 void DialogsProvider::PLOpenDir()
448 openDirectory( p_intf
, true, true );
451 void DialogsProvider::PLAppendDir()
453 openDirectory( p_intf
, true, false );
456 void DialogsProvider::MLAppendDir()
458 openDirectory( p_intf
, false , false );
464 void DialogsProvider::openAPlaylist()
466 QStringList files
= showSimpleOpen( qtr( "Open playlist..." ),
467 EXT_FILTER_PLAYLIST
);
468 foreach( QString file
, files
)
470 playlist_Import( THEPL
, qtu( toNativeSeparators( file
) ) );
474 void DialogsProvider::saveAPlaylist()
476 QFileDialog
*qfd
= new QFileDialog( NULL
,
477 qtr( "Save playlist as..." ),
478 qfu( p_intf
->p_sys
->psz_filepath
),
479 qtr( "XSPF playlist (*.xspf);; " ) +
480 qtr( "M3U playlist (*.m3u);; " ) +
481 qtr( "HTML playlist (*.html);;" ) +
482 qtr( "Any (*.*) " ) );
483 qfd
->setFileMode( QFileDialog::AnyFile
);
484 qfd
->setAcceptMode( QFileDialog::AcceptSave
);
485 qfd
->setConfirmOverwrite( true );
487 if( qfd
->exec() == QDialog::Accepted
)
489 if( qfd
->selectedFiles().count() > 0 )
491 static const char psz_xspf
[] = "export-xspf",
492 psz_m3u
[] = "export-m3u",
493 psz_html
[] = "export-html";
494 const char *psz_module
;
496 QString file
= qfd
->selectedFiles().first();
497 QString filter
= qfd
->selectedFilter();
498 const char* filt
= filter
.toAscii();
500 if( file
.contains( ".xsp" ) || filter
.contains( "XSPF" ) )
502 psz_module
= psz_xspf
;
503 if( !file
.contains( ".xsp" ) )
504 file
.append( ".xspf" );
506 else if( file
.contains( ".m3u" ) || filter
.contains( "M3U" ) )
508 psz_module
= psz_m3u
;
509 if( !file
.contains( ".m3u" ) )
510 file
.append( ".m3u" );
512 else if( file
.contains(".html" ) || filter
.contains( "HTML" ) )
514 psz_module
= psz_html
;
515 if( !file
.contains( "html" ) )
516 file
.append( ".html" );
520 msg_Err( p_intf
, "Impossible to recognise the file type" );
525 playlist_Export( THEPL
, qtu( toNativeSeparators( file
) ),
526 THEPL
->p_local_category
, psz_module
);
532 /****************************************************************************
534 ****************************************************************************/
536 void DialogsProvider::streamingDialog( QWidget
*parent
, QString mrl
,
537 bool b_transcode_only
)
539 SoutDialog
*s
= SoutDialog::getInstance( parent
, p_intf
, b_transcode_only
);
541 if( s
->exec() == QDialog::Accepted
)
543 msg_Dbg( p_intf
, "Sout mrl %s", qta( s
->getMrl() ) );
545 int i_len
= strlen( qtu( s
->getMrl() ) ) + 10;
546 char *psz_option
= (char*)malloc( i_len
);
547 snprintf( psz_option
, i_len
- 1, "%s", qtu( s
->getMrl() ) );
549 playlist_AddExt( THEPL
, qtu( mrl
), "Streaming",
550 PLAYLIST_APPEND
| PLAYLIST_GO
, PLAYLIST_END
,
551 -1, &psz_option
, 1, true, pl_Unlocked
);
552 RecentsMRL::getInstance( p_intf
)->addRecent( mrl
);
556 void DialogsProvider::openAndStreamingDialogs()
558 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
, false, OPEN_AND_STREAM
)
559 ->showTab( OPEN_FILE_TAB
);
562 void DialogsProvider::openAndTranscodingDialogs()
564 OpenDialog::getInstance( p_intf
->p_sys
->p_mi
, p_intf
, false, OPEN_AND_SAVE
)
565 ->showTab( OPEN_FILE_TAB
);
568 void DialogsProvider::loadSubtitlesFile()
570 input_thread_t
*p_input
= THEMIM
->getInput();
571 if( !p_input
) return;
573 input_item_t
*p_item
= input_GetItem( p_input
);
574 if( !p_item
) return;
576 char *path
= input_item_GetURI( p_item
);
577 if( !path
) path
= strdup( "" );
579 char *sep
= strrchr( path
, DIR_SEP_CHAR
);
580 if( sep
) *sep
= '\0';
582 QStringList qsl
= showSimpleOpen( qtr( "Open subtitles..." ),
587 foreach( qsFile
, qsl
)
589 if( !input_AddSubtitles( p_input
, qtu( toNativeSeparators( qsFile
) ),
591 msg_Warn( p_intf
, "unable to load subtitles from '%s'",
597 /****************************************************************************
599 ****************************************************************************/
601 void DialogsProvider::menuAction( QObject
*data
)
603 QVLCMenu::DoAction( p_intf
, data
);
606 void DialogsProvider::menuUpdateAction( QObject
*data
)
608 MenuFunc
*func
= qobject_cast
<MenuFunc
*>(data
);
610 func
->doFunc( p_intf
);
613 void DialogsProvider::SDMenuAction( QString data
)
615 char *psz_sd
= qtu( data
);
616 if( !playlist_IsServicesDiscoveryLoaded( THEPL
, psz_sd
) )
617 playlist_ServicesDiscoveryAdd( THEPL
, psz_sd
);
619 playlist_ServicesDiscoveryRemove( THEPL
, psz_sd
);
623 * Play the MRL contained in the Recently played menu.
625 void DialogsProvider::playMRL( const QString
&mrl
)
627 playlist_Add( THEPL
, qtu( mrl
) , NULL
,
628 PLAYLIST_APPEND
| PLAYLIST_GO
, PLAYLIST_END
, true, false );
630 RecentsMRL::getInstance( p_intf
)->addRecent( mrl
);
633 /*************************************
635 *************************************/
636 void DialogsProvider::doInteraction( intf_dialog_args_t
*p_arg
)
638 InteractionDialog
*qdialog
;
639 interaction_dialog_t
*p_dialog
= p_arg
->p_dialog
;
640 switch( p_dialog
->i_action
)
643 qdialog
= new InteractionDialog( p_intf
, p_dialog
);
644 p_dialog
->p_private
= (void*)qdialog
;
645 if( !(p_dialog
->i_status
== ANSWERED_DIALOG
) )
648 case INTERACT_UPDATE
:
649 qdialog
= (InteractionDialog
*)(p_dialog
->p_private
);
654 /* The INTERACT_NEW message was forgotten
655 so we must create the dialog and update it*/
656 qdialog
= new InteractionDialog( p_intf
, p_dialog
);
657 p_dialog
->p_private
= (void*)qdialog
;
658 if( !(p_dialog
->i_status
== ANSWERED_DIALOG
) )
665 msg_Dbg( p_intf
, "Hide the Interaction Dialog" );
666 qdialog
= (InteractionDialog
*)(p_dialog
->p_private
);
669 p_dialog
->i_status
= HIDDEN_DIALOG
;
671 case INTERACT_DESTROY
:
672 msg_Dbg( p_intf
, "Destroy the Interaction Dialog" );
673 qdialog
= (InteractionDialog
*)(p_dialog
->p_private
);
674 if( !p_dialog
->i_flags
& DIALOG_NONBLOCKING_ERROR
)
676 p_dialog
->i_status
= DESTROYED_DIALOG
;