source: smplayer/trunk/src/core.cpp@ 181

Last change on this file since 181 was 181, checked in by Silvan Scherrer, 9 years ago

smplayer: update trunk to version 16.8.0

  • Property svn:eol-style set to LF
File size: 118.0 KB
Line 
1/* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2016 Ricardo Villalba <[email protected]>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18
19#include "core.h"
20#include <QDir>
21#include <QFileInfo>
22#include <QRegExp>
23#include <QTextStream>
24#include <QUrl>
25#include <QNetworkProxy>
26
27#ifdef Q_OS_OS2
28#include <QEventLoop>
29#endif
30
31#include <cmath>
32
33#include "mplayerwindow.h"
34#include "desktopinfo.h"
35#include "helper.h"
36#include "paths.h"
37#include "preferences.h"
38#include "global.h"
39#include "config.h"
40#include "mplayerversion.h"
41#include "constants.h"
42#include "colorutils.h"
43#include "discname.h"
44#include "filters.h"
45#include "extensions.h"
46
47#ifdef Q_OS_WIN
48#include <windows.h> // To change app priority
49#include <QSysInfo> // To get Windows version
50#endif
51#ifdef SCREENSAVER_OFF
52#include "screensaver.h"
53#endif
54
55#include "filesettings.h"
56#include "filesettingshash.h"
57
58#ifdef TV_SUPPORT
59#include "tvlist.h"
60#include "tvsettings.h"
61#endif
62
63#ifdef YOUTUBE_SUPPORT
64#include "retrieveyoutubeurl.h"
65 #ifdef YT_USE_YTSIG
66 #include "ytsig.h"
67 #endif
68
69 #define PREF_YT_ENABLED pref->streaming_type == Preferences::StreamingYT || pref->streaming_type == Preferences::StreamingAuto
70#endif
71
72using namespace Global;
73
74Core::Core( MplayerWindow *mpw, QWidget* parent )
75 : QObject( parent )
76{
77 qRegisterMetaType<Core::State>("Core::State");
78
79 mplayerwindow = mpw;
80
81 _state = Stopped;
82
83 we_are_restarting = false;
84 just_loaded_external_subs = false;
85 just_unloaded_external_subs = false;
86 change_volume_after_unpause = false;
87
88#if DVDNAV_SUPPORT
89 dvdnav_title_is_menu = true; // Enabled by default for compatibility with previous versions of mplayer
90#endif
91
92 // Create file_settings
93 file_settings = 0;
94 changeFileSettingsMethod(pref->file_settings_method);
95
96 // TV settings
97#ifdef TV_SUPPORT
98 tv_settings = new TVSettings(Paths::iniPath());
99#endif
100
101 proc = PlayerProcess::createPlayerProcess(pref->mplayer_bin);
102
103 // Do this the first
104 connect( proc, SIGNAL(processExited()),
105 mplayerwindow->videoLayer(), SLOT(playingStopped()) );
106
107 connect( proc, SIGNAL(error(QProcess::ProcessError)),
108 mplayerwindow->videoLayer(), SLOT(playingStopped()) );
109
110 // Necessary to hide/unhide mouse cursor on black borders
111 connect( proc, SIGNAL(processExited()),
112 mplayerwindow, SLOT(playingStopped()) );
113
114 connect( proc, SIGNAL(error(QProcess::ProcessError)),
115 mplayerwindow, SLOT(playingStopped()) );
116
117
118 connect( proc, SIGNAL(receivedCurrentSec(double)),
119 this, SLOT(changeCurrentSec(double)) );
120
121 connect( proc, SIGNAL(receivedCurrentFrame(int)),
122 this, SIGNAL(showFrame(int)) );
123
124 connect( proc, SIGNAL(receivedPause()),
125 this, SLOT(changePause()) );
126
127 connect( proc, SIGNAL(processExited()),
128 this, SLOT(processFinished()), Qt::QueuedConnection );
129
130 connect( proc, SIGNAL(mplayerFullyLoaded()),
131 this, SLOT(finishRestart()), Qt::QueuedConnection );
132
133 connect( proc, SIGNAL(lineAvailable(QString)),
134 this, SIGNAL(logLineAvailable(QString)) );
135
136 connect( proc, SIGNAL(receivedCacheMessage(QString)),
137 this, SLOT(displayMessage(QString)) );
138
139 /*
140 connect( proc, SIGNAL(receivedCacheMessage(QString)),
141 this, SIGNAL(buffering()));
142 */
143
144 connect( proc, SIGNAL(receivedBuffering()),
145 this, SIGNAL(buffering()));
146
147 connect( proc, SIGNAL(receivedPlaying()),
148 this, SLOT(displayPlaying()));
149
150 connect( proc, SIGNAL(receivedCacheEmptyMessage(QString)),
151 this, SIGNAL(buffering()));
152
153 connect( proc, SIGNAL(receivedCreatingIndex(QString)),
154 this, SLOT(displayMessage(QString)) );
155
156 connect( proc, SIGNAL(receivedCreatingIndex(QString)),
157 this, SIGNAL(buffering()));
158
159 connect( proc, SIGNAL(receivedConnectingToMessage(QString)),
160 this, SLOT(displayMessage(QString)) );
161
162 connect( proc, SIGNAL(receivedConnectingToMessage(QString)),
163 this, SIGNAL(buffering()));
164
165 connect( proc, SIGNAL(receivedResolvingMessage(QString)),
166 this, SLOT(displayMessage(QString)) );
167
168 connect( proc, SIGNAL(receivedResolvingMessage(QString)),
169 this, SIGNAL(buffering()));
170
171 connect( proc, SIGNAL(receivedScreenshot(QString)),
172 this, SLOT(displayScreenshotName(QString)) );
173
174 connect( proc, SIGNAL(receivedUpdatingFontCache()),
175 this, SLOT(displayUpdatingFontCache()) );
176
177 connect( proc, SIGNAL(receivedScanningFont(QString)),
178 this, SLOT(displayMessage(QString)) );
179
180 connect( proc, SIGNAL(receivedWindowResolution(int,int)),
181 this, SLOT(gotWindowResolution(int,int)) );
182
183 connect( proc, SIGNAL(receivedNoVideo()),
184 this, SLOT(gotNoVideo()) );
185
186 connect( proc, SIGNAL(receivedVO(QString)),
187 this, SLOT(gotVO(QString)) );
188
189 connect( proc, SIGNAL(receivedAO(QString)),
190 this, SLOT(gotAO(QString)) );
191
192 connect( proc, SIGNAL(receivedEndOfFile()),
193 this, SLOT(fileReachedEnd()), Qt::QueuedConnection );
194
195 connect( proc, SIGNAL(receivedStartingTime(double)),
196 this, SLOT(gotStartingTime(double)) );
197
198 connect( proc, SIGNAL(receivedVideoBitrate(int)), this, SLOT(gotVideoBitrate(int)) );
199 connect( proc, SIGNAL(receivedAudioBitrate(int)), this, SLOT(gotAudioBitrate(int)) );
200
201 connect( proc, SIGNAL(receivedStreamTitle(QString)),
202 this, SLOT(streamTitleChanged(QString)) );
203
204 connect( proc, SIGNAL(receivedStreamTitleAndUrl(QString,QString)),
205 this, SLOT(streamTitleAndUrlChanged(QString,QString)) );
206
207 connect( proc, SIGNAL(failedToParseMplayerVersion(QString)),
208 this, SIGNAL(failedToParseMplayerVersion(QString)) );
209
210 connect( this, SIGNAL(mediaLoaded()), this, SLOT(checkIfVideoIsHD()), Qt::QueuedConnection );
211#if DELAYED_AUDIO_SETUP_ON_STARTUP
212 connect( this, SIGNAL(mediaLoaded()), this, SLOT(initAudioTrack()), Qt::QueuedConnection );
213#endif
214#if NOTIFY_SUB_CHANGES
215 connect( proc, SIGNAL(subtitleInfoChanged(const SubTracks &)),
216 this, SLOT(initSubtitleTrack(const SubTracks &)), Qt::QueuedConnection );
217 connect( proc, SIGNAL(subtitleInfoReceivedAgain(const SubTracks &)),
218 this, SLOT(setSubtitleTrackAgain(const SubTracks &)), Qt::QueuedConnection );
219#endif
220#if NOTIFY_AUDIO_CHANGES
221 connect( proc, SIGNAL(audioInfoChanged(const Tracks &)),
222 this, SLOT(initAudioTrack(const Tracks &)), Qt::QueuedConnection );
223#endif
224#if NOTIFY_VIDEO_CHANGES
225 connect( proc, SIGNAL(videoInfoChanged(const Tracks &)),
226 this, SLOT(initVideoTrack(const Tracks &)), Qt::QueuedConnection );
227#endif
228#if NOTIFY_CHAPTER_CHANGES
229 connect( proc, SIGNAL(chaptersChanged(const Chapters &)),
230 this, SLOT(updateChapterInfo(const Chapters &)), Qt::QueuedConnection );
231#endif
232
233#if DVDNAV_SUPPORT
234 connect( proc, SIGNAL(receivedDVDTitle(int)),
235 this, SLOT(dvdTitleChanged(int)), Qt::QueuedConnection );
236 connect( proc, SIGNAL(receivedDuration(double)),
237 this, SLOT(durationChanged(double)), Qt::QueuedConnection );
238
239 QTimer * ask_timer = new QTimer(this);
240 connect( ask_timer, SIGNAL(timeout()), this, SLOT(askForInfo()) );
241 ask_timer->start(5000);
242
243 connect( proc, SIGNAL(receivedTitleIsMenu()),
244 this, SLOT(dvdTitleIsMenu()) );
245 connect( proc, SIGNAL(receivedTitleIsMovie()),
246 this, SLOT(dvdTitleIsMovie()) );
247#endif
248
249 connect( proc, SIGNAL(receivedForbiddenText()), this, SIGNAL(receivedForbidden()) );
250
251 connect( this, SIGNAL(stateChanged(Core::State)),
252 this, SLOT(watchState(Core::State)) );
253
254 connect( this, SIGNAL(mediaInfoChanged()), this, SLOT(sendMediaInfo()) );
255
256 connect( proc, SIGNAL(error(QProcess::ProcessError)),
257 this, SIGNAL(mplayerFailed(QProcess::ProcessError)) );
258
259 //pref->load();
260 mset.reset();
261
262 // Mplayerwindow
263 connect( this, SIGNAL(aboutToStartPlaying()),
264 mplayerwindow->videoLayer(), SLOT(playingStarted()) );
265
266 // Necessary to hide/unhide mouse cursor on black borders
267 connect( this, SIGNAL(aboutToStartPlaying()),
268 mplayerwindow, SLOT(playingStarted()) );
269
270#if DVDNAV_SUPPORT
271 connect( mplayerwindow->videoLayer(), SIGNAL(mouseMoved(QPoint)),
272 this, SLOT(dvdnavUpdateMousePos(QPoint)) );
273#endif
274
275#if REPAINT_BACKGROUND_OPTION
276 mplayerwindow->videoLayer()->setRepaintBackground(pref->repaint_video_background);
277#endif
278 mplayerwindow->setMonitorAspect( pref->monitor_aspect_double() );
279
280#ifdef SCREENSAVER_OFF
281 // Windows or OS2 screensaver
282 win_screensaver = new WinScreenSaver();
283 connect( this, SIGNAL(aboutToStartPlaying()), this, SLOT(disableScreensaver()) );
284 connect( proc, SIGNAL(processExited()), this, SLOT(enableScreensaver()) );
285 connect( proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(enableScreensaver()) );
286#endif
287
288#ifdef YOUTUBE_SUPPORT
289 yt = new RetrieveYoutubeUrl(this);
290 yt->setUseHttpsMain(pref->yt_use_https_main);
291 yt->setUseHttpsVi(pref->yt_use_https_vi);
292
293 #ifdef YT_USE_SIG
294 QSettings * sigset = new QSettings(Paths::configPath() + "/sig.ini", QSettings::IniFormat, this);
295 yt->setSettings(sigset);
296 #endif
297
298 connect(yt, SIGNAL(gotPreferredUrl(const QString &, int)), this, SLOT(openYT(const QString &)));
299 connect(yt, SIGNAL(connecting(QString)), this, SLOT(connectingToYT(QString)));
300 connect(yt, SIGNAL(errorOcurred(int,QString)), this, SLOT(YTFailed(int,QString)));
301 connect(yt, SIGNAL(noSslSupport()), this, SIGNAL(noSslSupport()));
302 connect(yt, SIGNAL(signatureNotFound(const QString&)), this, SIGNAL(signatureNotFound(const QString&)));
303 connect(yt, SIGNAL(gotEmptyList()), this, SLOT(YTNoVideoUrl()));
304#endif
305
306 connect(this, SIGNAL(buffering()), this, SLOT(displayBuffering()));
307}
308
309
310Core::~Core() {
311 saveMediaInfo();
312
313 if (proc->isRunning()) stopMplayer();
314 proc->terminate();
315 delete proc;
316
317 delete file_settings;
318#ifdef TV_SUPPORT
319 delete tv_settings;
320#endif
321
322#ifdef SCREENSAVER_OFF
323 delete win_screensaver;
324#endif
325
326#ifdef YOUTUBE_SUPPORT
327 delete yt;
328#endif
329}
330
331void Core::changeFileSettingsMethod(QString method) {
332 qDebug("Core::changeFileSettingsMethod: %s", method.toUtf8().constData());
333 if (file_settings) delete file_settings;
334
335 if (method.toLower() == "hash")
336 file_settings = new FileSettingsHash(Paths::iniPath());
337 else
338 file_settings = new FileSettings(Paths::iniPath());
339}
340
341void Core::setState(State s) {
342 //qDebug() << "Core::setState: old state:" << _state << "new state:" << s;
343 if (s != _state) {
344 _state = s;
345 emit stateChanged(_state);
346 }
347}
348
349QString Core::stateToString() {
350 if (state()==Playing) return "Playing";
351 else
352 if (state()==Stopped) return "Stopped";
353 else
354 if (state()==Paused) return "Paused";
355 else
356 return "Unknown";
357}
358
359// Public restart
360void Core::restart() {
361 qDebug("Core::restart");
362 if (proc->isRunning()) {
363 restartPlay();
364 } else {
365 qDebug("Core::restart: mplayer is not running");
366 }
367}
368
369void Core::reload() {
370 qDebug("Core::reload");
371
372 stopMplayer();
373 we_are_restarting = false;
374
375 initPlaying();
376}
377
378void Core::saveMediaInfo() {
379 qDebug("Core::saveMediaInfo");
380
381 if (!pref->remember_media_settings) {
382 qDebug("Core::saveMediaInfo: saving settings for files is disabled");
383 return;
384 }
385
386 if (mdat.type == TYPE_STREAM && !pref->remember_stream_settings) {
387 qDebug("Core::saveMediaInfo: saving settings for streams is disabled");
388 return;
389 }
390
391 if ( (mdat.type == TYPE_FILE || mdat.type == TYPE_STREAM) && (!mdat.filename.isEmpty()) ) {
392 file_settings->saveSettingsFor(mdat.filename, mdat.type, mset, proc->player());
393 }
394#ifdef TV_SUPPORT
395 else
396 if ( (mdat.type == TYPE_TV) && (!mdat.filename.isEmpty()) ) {
397 tv_settings->saveSettingsFor(mdat.filename, mdat.type, mset, proc->player());
398 }
399#endif
400}
401
402void Core::restoreSettingsForMedia(const QString & name, int type) {
403 qDebug() << "Core::restoreSettingsForMedia:" << name << "type:" << type;
404
405 if (!pref->remember_media_settings) {
406 qDebug("Core::restoreSettingsForMedia: remember settings for files is disabled");
407 return;
408 }
409
410 if (type == TYPE_STREAM && !pref->remember_stream_settings) {
411 qDebug("Core::restoreSettingsForMedia: remember settings for streams is disabled");
412 return;
413 }
414
415 file_settings->loadSettingsFor(name, type, mset, proc->player());
416 qDebug("Core::restoreSettingsForMedia: media settings read");
417
418 // Resize the window and set the aspect as soon as possible
419 int saved_width = mset.win_width;
420 int saved_height = mset.win_height;
421 // 400x300 is the default size for win_width and win_height
422 // so we set them to 0 to avoid to resize the window on
423 // audio files
424 if ((saved_width == 400) && (saved_height == 300)) {
425 saved_width = 0;
426 saved_height = 0;
427 }
428 if ((saved_width > 0) && (saved_height > 0)) {
429 emit needResize(mset.win_width, mset.win_height);
430 changeAspectRatio(mset.aspect_ratio_id);
431 }
432
433 if (!pref->remember_time_pos) {
434 mset.current_sec = 0;
435 qDebug("Core::restoreSettingsForMedia: time pos reset to 0");
436 }
437}
438
439void Core::initializeMenus() {
440 qDebug("Core::initializeMenus");
441
442 emit menusNeedInitialize();
443}
444
445
446void Core::updateWidgets() {
447 qDebug("Core::updateWidgets");
448
449 emit widgetsNeedUpdate();
450}
451
452
453void Core::changeFullscreenMode(bool b) {
454 proc->setFullscreen(b);
455}
456
457void Core::displayTextOnOSD(QString text, int duration, int level, QString prefix) {
458 qDebug("Core::displayTextOnOSD: '%s'", text.toUtf8().constData());
459
460 if (proc->isRunning()) {
461 proc->setPausingPrefix(prefix);
462 proc->showOSDText(text, duration, level);
463 }
464}
465
466// Generic open, autodetect type
467void Core::open(QString file, int seek) {
468 qDebug("Core::open: '%s'", file.toUtf8().data());
469
470 if (file.startsWith("file:")) {
471 file = QUrl(file).toLocalFile();
472 qDebug("Core::open: converting url to local file: %s", file.toUtf8().constData());
473 }
474
475 QFileInfo fi(file);
476
477 if ( (fi.exists()) && (fi.suffix().toLower()=="iso") ) {
478 qDebug("Core::open: * identified as a dvd iso");
479#if DVDNAV_SUPPORT
480 openDVD( DiscName::joinDVD(0, file, pref->use_dvdnav) );
481#else
482 openDVD( DiscName::joinDVD(firstDVDTitle(), file, false) );
483#endif
484 }
485 else
486 if ( (fi.exists()) && (!fi.isDir()) ) {
487 qDebug("Core::open: * identified as local file");
488 // Local file
489 file = QFileInfo(file).absoluteFilePath();
490 openFile(file, seek);
491 }
492 else
493 if ( (fi.exists()) && (fi.isDir()) ) {
494 // Directory
495 qDebug("Core::open: * identified as a directory");
496 qDebug("Core::open: checking if contains a dvd");
497 file = QFileInfo(file).absoluteFilePath();
498 if (Helper::directoryContainsDVD(file)) {
499 qDebug("Core::open: * directory contains a dvd");
500#if DVDNAV_SUPPORT
501 openDVD( DiscName::joinDVD(firstDVDTitle(), file, pref->use_dvdnav) );
502#else
503 openDVD( DiscName::joinDVD(firstDVDTitle(), file, false) );
504#endif
505 } else {
506 qDebug("Core::open: * directory doesn't contain a dvd");
507 qDebug("Core::open: opening nothing");
508 }
509 }
510 else
511 if ((file.toLower().startsWith("dvd:")) || (file.toLower().startsWith("dvdnav:"))) {
512 qDebug("Core::open: * identified as dvd");
513 openDVD(file);
514 /*
515 QString f = file.lower();
516 QRegExp s("^dvd://(\\d+)");
517 if (s.indexIn(f) != -1) {
518 int title = s.cap(1).toInt();
519 openDVD(title);
520 } else {
521 qWarning("Core::open: couldn't parse dvd title, playing first one");
522 openDVD();
523 }
524 */
525 }
526 else
527#ifdef BLURAY_SUPPORT
528 if (file.toLower().startsWith("br:")) {
529 qDebug("Core::open: * identified as blu-ray");
530 openBluRay(file);
531 }
532 else
533#endif
534 if (file.toLower().startsWith("vcd:")) {
535 qDebug("Core::open: * identified as vcd");
536
537 QString f = file.toLower();
538 QRegExp s("^vcd://(\\d+)");
539 if (s.indexIn(f) != -1) {
540 int title = s.cap(1).toInt();
541 openVCD(title);
542 } else {
543 qWarning("Core::open: couldn't parse vcd title, playing first one");
544 openVCD();
545 }
546 }
547 else
548 if (file.toLower().startsWith("cdda:")) {
549 qDebug("Core::open: * identified as cdda");
550
551 QString f = file.toLower();
552 QRegExp s("^cdda://(\\d+)");
553 if (s.indexIn(f) != -1) {
554 int title = s.cap(1).toInt();
555 openAudioCD(title);
556 } else {
557 qWarning("Core::open: couldn't parse cdda title, playing first one");
558 openAudioCD();
559 }
560 }
561#ifdef TV_SUPPORT
562 else
563 if ((file.toLower().startsWith("dvb:")) || (file.toLower().startsWith("tv:"))) {
564 qDebug("Core::open: * identified as TV");
565 openTV(file);
566 }
567#endif
568 else {
569 qDebug("Core::open: * not identified, playing as stream");
570 openStream(file);
571 }
572}
573
574void Core::openFile(QString filename, int seek) {
575 qDebug("Core::openFile: '%s'", filename.toUtf8().data());
576
577 QFileInfo fi(filename);
578 if (fi.exists()) {
579 playNewFile(fi.absoluteFilePath(), seek);
580 } else {
581 //File doesn't exists
582 //TODO: error message
583 }
584}
585
586#ifdef YOUTUBE_SUPPORT
587void Core::openYT(const QString & url) {
588 qDebug("Core::openYT: %s", url.toUtf8().constData());
589 openStream(url);
590 yt->close();
591}
592
593void Core::connectingToYT(QString host) {
594 emit showMessage( tr("Connecting to %1").arg(host) );
595}
596
597void Core::YTFailed(int /*error_number*/, QString /*error_str*/) {
598 emit showMessage( tr("Unable to retrieve the Youtube page") );
599}
600
601void Core::YTNoVideoUrl() {
602 emit showMessage( tr("Unable to locate the URL of the video") );
603}
604#endif
605
606#ifdef SCREENSAVER_OFF
607void Core::enableScreensaver() {
608 qDebug("Core::enableScreensaver");
609 if (pref->turn_screensaver_off) {
610 win_screensaver->enable();
611 }
612}
613
614void Core::disableScreensaver() {
615 qDebug("Core::disableScreensaver");
616 if (pref->turn_screensaver_off) {
617 win_screensaver->disable();
618 }
619}
620#endif
621
622void Core::loadSub(const QString & sub ) {
623 if ( (!sub.isEmpty()) && (QFile::exists(sub)) ) {
624#if NOTIFY_SUB_CHANGES
625 mset.external_subtitles = sub;
626 just_loaded_external_subs = true;
627
628 QFileInfo fi(sub);
629 bool is_idx = (fi.suffix().toLower() == "idx");
630 if (proc->isMPV()) is_idx = false; // Hack to ignore the idx extension with mpv
631
632 if ((pref->fast_load_sub) && (!is_idx) && (mset.external_subtitles_fps == MediaSettings::SFPS_None)) {
633 QString sub_file = sub;
634 #ifdef Q_OS_WIN
635 if (pref->use_short_pathnames) {
636 sub_file = Helper::shortPathName(sub);
637 // For some reason it seems it's necessary to change the path separator to unix style
638 // otherwise mplayer fails to load it
639 sub_file = sub_file.replace("\\","/");
640 }
641 #endif
642 proc->setExternalSubtitleFile(sub_file);
643 } else {
644 restartPlay();
645 }
646#else
647 mset.external_subtitles = sub;
648 just_loaded_external_subs = true;
649 restartPlay();
650#endif
651 } else {
652 qWarning("Core::loadSub: file '%s' is not valid", sub.toUtf8().constData());
653 }
654}
655
656void Core::unloadSub() {
657 if ( !mset.external_subtitles.isEmpty() ) {
658 mset.external_subtitles = "";
659 just_unloaded_external_subs = true;
660 restartPlay();
661 }
662}
663
664void Core::loadAudioFile(const QString & audiofile) {
665 if (!audiofile.isEmpty()) {
666 mset.external_audio = audiofile;
667 restartPlay();
668 }
669}
670
671void Core::unloadAudioFile() {
672 if (!mset.external_audio.isEmpty()) {
673 mset.external_audio = "";
674 restartPlay();
675 }
676}
677
678/*
679void Core::openDVD( bool from_folder, QString directory) {
680 qDebug("Core::openDVD");
681
682 if (from_folder) {
683 if (!directory.isEmpty()) {
684 QFileInfo fi(directory);
685 if ( (fi.exists()) && (fi.isDir()) ) {
686 pref->dvd_directory = directory;
687 pref->play_dvd_from_hd = true;
688 openDVD();
689 } else {
690 qDebug("Core::openDVD: directory '%s' is not valid", directory.toUtf8().data());
691 }
692 } else {
693 qDebug("Core::openDVD: directory is empty");
694 }
695 } else {
696 pref->play_dvd_from_hd = false;
697 openDVD();
698 }
699}
700
701void Core::openDVD() {
702 openDVD(1);
703}
704
705void Core::openDVD(int title) {
706 qDebug("Core::openDVD: %d", title);
707
708 if (proc->isRunning()) {
709 stopMplayer();
710 }
711
712 // Save data of previous file:
713 saveMediaInfo();
714
715 mdat.reset();
716 mdat.filename = "dvd://" + QString::number(title);
717 mdat.type = TYPE_DVD;
718
719 mset.reset();
720
721 mset.current_title_id = title;
722 mset.current_angle_id = 1;
723
724 initializeMenus();
725
726 initPlaying();
727}
728*/
729
730void Core::openVCD(int title) {
731 qDebug("Core::openVCD: %d", title);
732
733 if (title == -1) title = pref->vcd_initial_title;
734
735 if (proc->isRunning()) {
736 stopMplayer();
737 }
738
739 // Save data of previous file:
740 saveMediaInfo();
741
742 mdat.reset();
743 mdat.filename = "vcd://" + QString::number(title);
744 mdat.type = TYPE_VCD;
745
746 mset.reset();
747
748 mset.current_title_id = title;
749 mset.current_angle_id = -1;
750
751 /* initializeMenus(); */
752
753 initPlaying();
754}
755
756void Core::openAudioCD(int title) {
757 qDebug("Core::openAudioCD: %d", title);
758
759 if (title == -1) title = 1;
760
761 if (proc->isRunning()) {
762 stopMplayer();
763 }
764
765 // Save data of previous file:
766 saveMediaInfo();
767
768 mdat.reset();
769 mdat.filename = "cdda://" + QString::number(title);
770 mdat.type = TYPE_AUDIO_CD;
771
772 mset.reset();
773
774 mset.current_title_id = title;
775 mset.current_angle_id = -1;
776
777 /* initializeMenus(); */
778
779 initPlaying();
780}
781
782void Core::openDVD(QString dvd_url) {
783 qDebug("Core::openDVD: '%s'", dvd_url.toUtf8().data());
784
785 //Checks
786 DiscData disc_data = DiscName::split(dvd_url);
787 QString folder = disc_data.device;
788 int title = disc_data.title;
789
790 if (title == -1) {
791 qWarning("Core::openDVD: title invalid, not playing dvd");
792 return;
793 }
794
795 if (folder.isEmpty()) {
796 qDebug("Core::openDVD: not folder");
797 } else {
798 QFileInfo fi(folder);
799 if ( (!fi.exists()) /*|| (!fi.isDir())*/ ) {
800 qWarning("Core::openDVD: folder invalid, not playing dvd");
801 return;
802 }
803 }
804
805 if (proc->isRunning()) {
806 stopMplayer();
807 we_are_restarting = false;
808 }
809
810 // Save data of previous file:
811 saveMediaInfo();
812
813 mdat.reset();
814 mdat.filename = dvd_url;
815 mdat.type = TYPE_DVD;
816
817 mset.reset();
818
819 mset.current_title_id = title;
820 mset.current_angle_id = 1;
821
822 /* initializeMenus(); */
823
824 initPlaying();
825}
826
827
828#ifdef BLURAY_SUPPORT
829/**
830 * Opens a BluRay, taking advantage of mplayer's capabilities to do so.
831 */
832void Core::openBluRay(QString bluray_url) {
833 qDebug("Core::openBluRay: '%s'", bluray_url.toUtf8().data());
834
835 //Checks
836 DiscData disc_data = DiscName::split(bluray_url);
837 QString folder = disc_data.device;
838 int title = disc_data.title;
839
840 if (title == -1) {
841 qWarning("Core::openBluRay: title invalid, not playing bluray");
842 return;
843 }
844
845 QFileInfo fi(folder);
846 if ( (!fi.exists()) || (!fi.isDir()) ) {
847 qWarning("Core::openBluRay: folder invalid, not playing bluray");
848 return;
849 }
850
851 if (proc->isRunning()) {
852 stopMplayer();
853 we_are_restarting = false;
854 }
855
856 // Save data of previous file:
857 saveMediaInfo();
858
859 mdat.reset();
860 mdat.filename = bluray_url;
861 mdat.type = TYPE_BLURAY;
862
863 mset.reset();
864
865 mset.current_title_id = title;
866 mset.current_angle_id = 1;
867
868 /* initializeMenus(); */
869
870 initPlaying();
871}
872#endif
873
874#ifdef TV_SUPPORT
875void Core::openTV(QString channel_id) {
876 qDebug("Core::openTV: '%s'", channel_id.toUtf8().constData());
877
878 if (proc->isRunning()) {
879 stopMplayer();
880 we_are_restarting = false;
881 }
882
883 // Save data of previous file:
884 saveMediaInfo();
885
886 // Use last channel if the name is just "dvb://" or "tv://"
887 if ((channel_id == "dvb://") && (!pref->last_dvb_channel.isEmpty())) {
888 channel_id = pref->last_dvb_channel;
889 }
890 else
891 if ((channel_id == "tv://") && (!pref->last_tv_channel.isEmpty())) {
892 channel_id = pref->last_tv_channel;
893 }
894
895 // Save last channel
896 if (channel_id.startsWith("dvb://")) pref->last_dvb_channel = channel_id;
897 else
898 if (channel_id.startsWith("tv://")) pref->last_tv_channel = channel_id;
899
900 mdat.reset();
901 mdat.filename = channel_id;
902 mdat.type = TYPE_TV;
903
904 mset.reset();
905
906 // Set the default deinterlacer for TV
907 mset.current_deinterlacer = pref->initial_tv_deinterlace;
908
909 if (pref->remember_media_settings) {
910 // Check if we already have info about this file
911 if (tv_settings->existSettingsFor(channel_id, mdat.type)) {
912 qDebug("Core::openTV: we have settings for this file!!!");
913
914 // In this case we read info from config
915 tv_settings->loadSettingsFor(channel_id, mdat.type, mset, proc->player());
916 qDebug("Core::openTV: media settings read");
917 }
918 }
919
920 /* initializeMenus(); */
921
922 initPlaying();
923}
924#endif
925
926void Core::openStream(QString name) {
927 qDebug("Core::openStream: '%s'", name.toUtf8().data());
928
929#ifdef YOUTUBE_SUPPORT
930 if (PREF_YT_ENABLED) {
931 // Check if the stream is a youtube url
932 QString yt_full_url = yt->fullUrl(name);
933 if (!yt_full_url.isEmpty()) {
934 qDebug("Core::openStream: youtube url detected: %s", yt_full_url.toLatin1().constData());
935 name = yt_full_url;
936 yt->setPreferredQuality( (RetrieveYoutubeUrl::Quality) pref->yt_quality );
937 qDebug("Core::openStream: user_agent: '%s'", pref->yt_user_agent.toUtf8().constData());
938 /*if (!pref->yt_user_agent.isEmpty()) yt->setUserAgent(pref->yt_user_agent); */
939 yt->setUserAgent(pref->yt_user_agent);
940 #ifdef YT_USE_YTSIG
941 YTSig::setScriptFile( Paths::configPath() + "/yt.js" );
942 #endif
943 yt->fetchPage(name);
944 return;
945 }
946 }
947#endif
948
949 if (proc->isRunning()) {
950 stopMplayer();
951 we_are_restarting = false;
952 }
953
954 // Save data of previous file:
955 saveMediaInfo();
956
957 mdat.reset();
958 mdat.filename = name;
959 mdat.type = TYPE_STREAM;
960
961 mset.reset();
962
963 #ifdef YOUTUBE_SUPPORT
964 if (PREF_YT_ENABLED) {
965 if (mdat.filename == yt->latestPreferredUrl()) name = yt->origUrl();
966 }
967 #endif
968 // Check if we already have info about this file
969 if (file_settings->existSettingsFor(name, mdat.type)) {
970 qDebug("Core::openStream: we have settings for this stream");
971 restoreSettingsForMedia(name, mdat.type);
972 }
973
974 /* initializeMenus(); */
975
976 initPlaying();
977}
978
979
980void Core::playNewFile(QString file, int seek) {
981 qDebug("Core::playNewFile: '%s'", file.toUtf8().data());
982
983 if (proc->isRunning()) {
984 stopMplayer();
985 we_are_restarting = false;
986 }
987
988 // Save data of previous file:
989 saveMediaInfo();
990
991 mdat.reset();
992 mdat.filename = file;
993 mdat.type = TYPE_FILE;
994
995 int old_volume = mset.volume;
996 mset.reset();
997
998 // Check if we already have info about this file
999 if (file_settings->existSettingsFor(file, mdat.type)) {
1000 qDebug("Core::playNewFile: we have settings for this file");
1001 restoreSettingsForMedia(file, mdat.type);
1002 } else {
1003 // Recover volume
1004 mset.volume = old_volume;
1005 }
1006
1007 /* initializeMenus(); */
1008
1009 qDebug("Core::playNewFile: volume: %d, old_volume: %d", mset.volume, old_volume);
1010 initPlaying(seek);
1011}
1012
1013
1014void Core::restartPlay() {
1015 we_are_restarting = true;
1016 initPlaying();
1017}
1018
1019void Core::initPlaying(int seek) {
1020 qDebug("Core::initPlaying");
1021
1022 /*
1023 mdat.list();
1024 mset.list();
1025 */
1026
1027 /* updateWidgets(); */
1028
1029 mplayerwindow->hideLogo();
1030
1031 if (proc->isRunning()) {
1032 stopMplayer();
1033 }
1034
1035 int start_sec = (int) mset.current_sec;
1036 if (seek > -1) start_sec = seek;
1037
1038#ifdef YOUTUBE_SUPPORT
1039 if (PREF_YT_ENABLED) {
1040 // Avoid to pass to mplayer the youtube page url
1041 if (mdat.type == TYPE_STREAM) {
1042 if (mdat.filename == yt->origUrl()) {
1043 mdat.filename = yt->latestPreferredUrl();
1044 }
1045 }
1046 }
1047#endif
1048
1049 startMplayer( mdat.filename, start_sec );
1050}
1051
1052// This is reached when a new video has just started playing
1053// and maybe we need to give some defaults
1054void Core::newMediaPlaying() {
1055 qDebug("Core::newMediaPlaying: --- start ---");
1056
1057 QString file = mdat.filename;
1058 int type = mdat.type;
1059 mdat = proc->mediaData();
1060 mdat.filename = file;
1061 mdat.type = type;
1062
1063 initializeMenus(); // Old
1064
1065 // Copy the demuxer
1066 mset.current_demuxer = mdat.demuxer;
1067
1068 // Video
1069 #if 0
1070 if ( (mset.current_video_id == MediaSettings::NoneSelected) &&
1071 (mdat.videos.numItems() > 0) )
1072 {
1073 changeVideo( mdat.videos.itemAt(0).ID(), false ); // Don't allow to restart
1074 }
1075 #endif
1076
1077#if !DELAYED_AUDIO_SETUP_ON_STARTUP && !NOTIFY_AUDIO_CHANGES
1078 // First audio if none selected
1079 if ( (mset.current_audio_id == MediaSettings::NoneSelected) &&
1080 (mdat.audios.numItems() > 0) )
1081 {
1082 // Don't set mset.current_audio_id here! changeAudio will do.
1083 // Otherwise changeAudio will do nothing.
1084
1085 int audio = mdat.audios.itemAt(0).ID(); // First one
1086 if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) {
1087 audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID();
1088 }
1089
1090 // Check if one of the audio tracks is the user preferred.
1091 if (!pref->audio_lang.isEmpty()) {
1092 int res = mdat.audios.findLang( pref->audio_lang );
1093 if (res != -1) audio = res;
1094 }
1095
1096 // Change the audio without restarting mplayer, it's not
1097 // safe to do it here.
1098 changeAudio( audio, false );
1099
1100 }
1101#endif
1102
1103#if !NOTIFY_SUB_CHANGES
1104 // Subtitles
1105 if (mset.external_subtitles.isEmpty()) {
1106 if (pref->autoload_sub) {
1107 //Select first subtitle if none selected
1108 if (mset.current_sub_id == MediaSettings::NoneSelected) {
1109 int sub = mdat.subs.selectOne( pref->subtitle_lang, pref->initial_subtitle_track-1 );
1110 changeSubtitle( sub );
1111 }
1112 } else {
1113 changeSubtitle( MediaSettings::SubNone );
1114 }
1115 }
1116#endif
1117
1118 mdat.initialized = true;
1119
1120 // MPlayer doesn't display the length in ID_LENGTH for audio CDs...
1121 if ((mdat.duration == 0) && (mdat.type == TYPE_AUDIO_CD)) {
1122 /*
1123 qDebug(" *** get duration here from title info *** ");
1124 qDebug(" *** current title: %d", mset.current_title_id );
1125 */
1126 if (mset.current_title_id > 0) {
1127 mdat.duration = mdat.titles.item(mset.current_title_id).duration();
1128 }
1129 }
1130
1131 /* updateWidgets(); */
1132
1133 mdat.list();
1134 mset.list();
1135
1136 qDebug("Core::newMediaPlaying: --- end ---");
1137}
1138
1139void Core::finishRestart() {
1140 qDebug("Core::finishRestart: --- start ---");
1141
1142 if (!we_are_restarting) {
1143 newMediaPlaying();
1144 //QTimer::singleShot(1000, this, SIGNAL(mediaStartPlay()));
1145 emit mediaStartPlay();
1146 }
1147
1148 if (we_are_restarting) {
1149 // Update info about codecs and demuxer
1150 mdat.video_codec = proc->mediaData().video_codec;
1151 mdat.audio_codec = proc->mediaData().audio_codec;
1152 mdat.demuxer = proc->mediaData().demuxer;
1153 }
1154
1155 if (forced_titles.contains(mdat.filename)) {
1156 mdat.clip_name = forced_titles[mdat.filename];
1157 }
1158
1159#ifdef YOUTUBE_SUPPORT
1160 if (PREF_YT_ENABLED) {
1161 // Change the real url with the youtube page url and set the title
1162 if (mdat.type == TYPE_STREAM) {
1163 if (mdat.filename == yt->latestPreferredUrl()) {
1164 mdat.filename = yt->origUrl();
1165 mdat.stream_title = yt->urlTitle();
1166 }
1167 }
1168 }
1169#endif
1170
1171#if !NOTIFY_SUB_CHANGES
1172 // Subtitles
1173 //if (we_are_restarting) {
1174 if ( (just_loaded_external_subs) || (just_unloaded_external_subs) ) {
1175 qDebug("Core::finishRestart: processing new subtitles");
1176
1177 // Just to simplify things
1178 if (mset.current_sub_id == MediaSettings::NoneSelected) {
1179 mset.current_sub_id = MediaSettings::SubNone;
1180 }
1181
1182 // Save current sub
1183 SubData::Type type;
1184 int ID;
1185 int old_item = -1;
1186 if ( mset.current_sub_id != MediaSettings::SubNone ) {
1187 old_item = mset.current_sub_id;
1188 type = mdat.subs.itemAt(old_item).type();
1189 ID = mdat.subs.itemAt(old_item).ID();
1190 }
1191
1192 // Use the subtitle info from mplayerprocess
1193 qDebug( "Core::finishRestart: copying sub data from proc to mdat");
1194 mdat.subs = proc->mediaData().subs;
1195 initializeMenus();
1196 int item = MediaSettings::SubNone;
1197
1198 // Try to recover old subtitle
1199 if (just_unloaded_external_subs) {
1200 if (old_item > -1) {
1201 int new_item = mdat.subs.find(type, ID);
1202 if (new_item > -1) item = new_item;
1203 }
1204 }
1205
1206 // If we've just loaded a subtitle file
1207 // select one if the user wants to autoload
1208 // one subtitle
1209 if (just_loaded_external_subs) {
1210 if ( (pref->autoload_sub) && (item == MediaSettings::SubNone) ) {
1211 qDebug("Core::finishRestart: cannot find previous subtitle");
1212 qDebug("Core::finishRestart: selecting a new one");
1213 item = mdat.subs.selectOne( pref->subtitle_lang );
1214 }
1215 }
1216 changeSubtitle( item );
1217 just_loaded_external_subs = false;
1218 just_unloaded_external_subs = false;
1219 } else {
1220 // Normal restart, subtitles haven't changed
1221 // Recover current subtitle
1222 changeSubtitle( mset.current_sub_id );
1223 changeSecondarySubtitle( mset.current_secondary_sub_id );
1224 }
1225#endif
1226
1227 we_are_restarting = false;
1228
1229 changeAspectRatio(mset.aspect_ratio_id);
1230
1231 if (pref->mplayer_additional_options.contains("-volume")) {
1232 qDebug("Core::finishRestart: don't set volume since -volume is used");
1233 } else {
1234 // Code to set the volume, used when mplayer didn't have the -volume option
1235 /*
1236 if (pref->global_volume) {
1237 bool was_muted = pref->mute;
1238 setVolume( pref->volume, true);
1239 if (was_muted) mute(true);
1240 } else {
1241 bool was_muted = mset.mute;
1242 setVolume( mset.volume, true );
1243 if (was_muted) mute(true);
1244 }
1245 */
1246 int vol = (pref->global_volume ? pref->volume : mset.volume);
1247 volumeChanged(vol);
1248
1249 if (proc->isMPlayer() && pref->mute) {
1250 // Set mute here because mplayer doesn't have an option to set mute from the command line
1251 mute(true);
1252 }
1253 }
1254
1255#if 0
1256// Old. Gamma already set with option -gamma
1257 if (pref->change_video_equalizer_on_startup && (mset.gamma != 0)) {
1258 int gamma = mset.gamma;
1259 mset.gamma = -1000; // if mset.gamma == new value, mset.gamma is not changed!
1260 setGamma( gamma );
1261 }
1262#endif
1263 // Hack to be sure that the equalizers are up to date
1264 emit videoEqualizerNeedsUpdate();
1265 emit audioEqualizerNeedsUpdate();
1266
1267 changeZoom(mset.zoom_factor);
1268
1269 // Toggle subtitle visibility
1270 changeSubVisibility(pref->sub_visibility);
1271
1272 // A-B marker
1273 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
1274
1275 // Initialize the OSD level
1276 QTimer::singleShot(pref->osd_delay, this, SLOT(initializeOSD()));
1277
1278 emit mediaLoaded();
1279 emit mediaInfoChanged();
1280 emit newDuration(mdat.duration);
1281
1282 emit mediaDataReceived(mdat);
1283
1284 updateWidgets(); // New
1285
1286 qDebug("Core::finishRestart: --- end ---");
1287}
1288
1289void Core::initializeOSD() {
1290 changeOSD(pref->osd);
1291}
1292
1293void Core::stop()
1294{
1295 qDebug("Core::stop");
1296 qDebug("Core::stop: state: %s", stateToString().toUtf8().data());
1297
1298 if (state()==Stopped) {
1299 // if pressed stop twice, reset video to the beginning
1300 qDebug("Core::stop: mset.current_sec: %f", mset.current_sec);
1301 mset.current_sec = 0;
1302 qDebug("Core::stop: mset.current_sec set to 0");
1303 emit showTime( mset.current_sec );
1304 #ifdef SEEKBAR_RESOLUTION
1305 emit positionChanged( 0 );
1306 #else
1307 emit posChanged( 0 );
1308 #endif
1309 //updateWidgets();
1310 }
1311
1312 stopMplayer();
1313 emit mediaStoppedByUser();
1314
1315 if (pref->reset_stop) {
1316 mset.current_sec = 0;
1317 emit showTime( mset.current_sec );
1318 #ifdef SEEKBAR_RESOLUTION
1319 emit positionChanged( 0 );
1320 #else
1321 emit posChanged( 0 );
1322 #endif
1323 }
1324}
1325
1326
1327void Core::play() {
1328 qDebug("Core::play");
1329
1330 if ((proc->isRunning()) && (state()==Paused)) {
1331 proc->setPause(false);
1332 }
1333 else
1334 if ((proc->isRunning()) && (state()==Playing)) {
1335 // nothing to do, continue playing
1336 }
1337 else {
1338 // if we're stopped, play it again
1339 if ( !mdat.filename.isEmpty() ) {
1340 /*
1341 qDebug( "current_sec: %f, duration: %f", mset.current_sec, mdat.duration);
1342 if ( (floor(mset.current_sec)) >= (floor(mdat.duration)) ) {
1343 mset.current_sec = 0;
1344 }
1345 */
1346 restartPlay();
1347 } else {
1348 emit noFileToPlay();
1349 }
1350 }
1351}
1352
1353void Core::pause_and_frame_step() {
1354 qDebug("Core::pause_and_frame_step");
1355
1356 if (proc->isRunning()) {
1357 if (state() == Paused) {
1358 proc->frameStep();
1359 } else {
1360 proc->setPause(true);
1361 }
1362 }
1363}
1364
1365void Core::pause() {
1366 qDebug("Core::pause: current state: %s", stateToString().toUtf8().data());
1367
1368 if (proc->isRunning()) {
1369 // Pauses and unpauses
1370 if (state() == Paused) proc->setPause(false); else proc->setPause(true);
1371 }
1372}
1373
1374void Core::play_or_pause() {
1375 if (proc->isRunning()) {
1376 pause();
1377 } else {
1378 play();
1379 }
1380}
1381
1382void Core::frameStep() {
1383 qDebug("Core::frameStep");
1384
1385 if (proc->isRunning()) {
1386 proc->frameStep();
1387 }
1388}
1389
1390void Core::frameBackStep() {
1391 qDebug("Core::frameBackStep");
1392
1393 if (proc->isRunning()) {
1394 proc->frameBackStep();
1395 }
1396}
1397
1398void Core::screenshot() {
1399 qDebug("Core::screenshot");
1400
1401 if ( (!pref->screenshot_directory.isEmpty()) &&
1402 (QFileInfo(pref->screenshot_directory).isDir()) )
1403 {
1404 proc->setPausingPrefix(pausing_prefix());
1405 proc->takeScreenshot(PlayerProcess::Single, pref->subtitles_on_screenshots);
1406 qDebug("Core::screenshot: taken screenshot");
1407 } else {
1408 qDebug("Core::screenshot: error: directory for screenshots not valid");
1409 emit showMessage( tr("Screenshot NOT taken, folder not configured") );
1410 }
1411}
1412
1413void Core::screenshots() {
1414 qDebug("Core::screenshots");
1415
1416 if ( (!pref->screenshot_directory.isEmpty()) &&
1417 (QFileInfo(pref->screenshot_directory).isDir()) )
1418 {
1419 proc->takeScreenshot(PlayerProcess::Multiple, pref->subtitles_on_screenshots);
1420 } else {
1421 qDebug("Core::screenshots: error: directory for screenshots not valid");
1422 emit showMessage( tr("Screenshots NOT taken, folder not configured") );
1423 }
1424}
1425
1426#ifdef CAPTURE_STREAM
1427void Core::switchCapturing() {
1428 qDebug("Core::switchCapturing");
1429 proc->switchCapturing();
1430}
1431#endif
1432
1433void Core::processFinished()
1434{
1435 qDebug("Core::processFinished");
1436 qDebug("Core::processFinished: we_are_restarting: %d", we_are_restarting);
1437
1438 //mset.current_sec = 0;
1439
1440 if (!we_are_restarting) {
1441 qDebug("Core::processFinished: play has finished!");
1442 setState(Stopped);
1443 //emit stateChanged(state());
1444 }
1445
1446 int exit_code = proc->exitCode();
1447 qDebug("Core::processFinished: exit_code: %d", exit_code);
1448 if (exit_code != 0) {
1449 setState(Stopped);
1450 emit stateChanged(Stopped);
1451 emit mplayerFinishedWithError(exit_code);
1452 }
1453}
1454
1455void Core::fileReachedEnd() {
1456 /*
1457 if (mdat.type == TYPE_VCD) {
1458 // If the first vcd title has nothing, it doesn't start to play
1459 // and menus are not initialized.
1460 initializeMenus();
1461 }
1462 */
1463
1464 // If we're at the end of the movie, reset to 0
1465 mset.current_sec = 0;
1466 updateWidgets();
1467
1468 emit mediaFinished();
1469}
1470
1471#if SEEKBAR_RESOLUTION
1472void Core::goToPosition(int value) {
1473 qDebug("Core::goToPosition: value: %d", value);
1474
1475 if (pref->relative_seeking) {
1476 goToPos( (double) value / (SEEKBAR_RESOLUTION / 100) );
1477 }
1478 else {
1479 if (mdat.duration > 0) {
1480 int jump_time = (int) mdat.duration * value / SEEKBAR_RESOLUTION;
1481 goToSec(jump_time);
1482 }
1483 }
1484}
1485
1486void Core::goToPos(double perc) {
1487 qDebug("Core::goToPos: per: %f", perc);
1488 seek_cmd(perc, 1);
1489}
1490#else
1491void Core::goToPos(int perc) {
1492 qDebug("Core::goToPos: per: %d", perc);
1493 seek_cmd(perc, 1);
1494}
1495#endif
1496
1497
1498void Core::startMplayer( QString file, double seek ) {
1499 qDebug("Core::startMplayer");
1500
1501 if (file.isEmpty()) {
1502 qWarning("Core:startMplayer: file is empty!");
1503 return;
1504 }
1505
1506 if (proc->isRunning()) {
1507 qWarning("Core::startMplayer: MPlayer still running!");
1508 return;
1509 }
1510
1511#ifdef YOUTUBE_SUPPORT
1512 // Stop any pending request
1513 #if 0
1514 qDebug("Core::startMplayer: yt state: %d", yt->state());
1515 if (yt->state() != QHttp::Unconnected) {
1516 //yt->abort(); /* Make the app to crash, don't know why */
1517 }
1518 #endif
1519 yt->close();
1520#endif
1521
1522 // DVD
1523 QString dvd_folder;
1524 int dvd_title = -1;
1525 if (mdat.type==TYPE_DVD) {
1526 DiscData disc_data = DiscName::split(file);
1527 dvd_folder = disc_data.device;
1528 if (dvd_folder.isEmpty()) dvd_folder = pref->dvd_device;
1529 dvd_title = disc_data.title;
1530 file = disc_data.protocol + "://";
1531 if (dvd_title > -1) file += QString::number(dvd_title);
1532 }
1533
1534 // Check URL playlist
1535 bool url_is_playlist = false;
1536 if (file.endsWith("|playlist")) {
1537 url_is_playlist = true;
1538 file = file.remove("|playlist");
1539 } else {
1540 QUrl url(file);
1541 qDebug("Core::startMplayer: checking if stream is a playlist");
1542 qDebug("Core::startMplayer: url path: '%s'", url.path().toUtf8().constData());
1543
1544 if (url.scheme().toLower() != "ffmpeg") {
1545 QRegExp rx("\\.ram$|\\.asx$|\\.m3u$|\\.m3u8$|\\.pls$", Qt::CaseInsensitive);
1546 url_is_playlist = (rx.indexIn(url.path()) != -1);
1547 }
1548 }
1549 qDebug("Core::startMplayer: url_is_playlist: %d", url_is_playlist);
1550
1551 // Hack: don't use -ss with m3u(8) streams
1552 if (mdat.type == TYPE_STREAM) {
1553 QString extension = Extensions::extensionFromUrl(file);
1554 qDebug() << "Core::startMplayer: URL extension:" << extension;
1555 if (extension.contains("m3u")) {
1556 seek = 0;
1557 }
1558 }
1559
1560 // Check if a m4a file exists with the same name of file, in that cause if will be used as audio
1561 if (pref->autoload_m4a && mset.external_audio.isEmpty()) {
1562 QFileInfo fi(file);
1563 if (fi.exists() && !fi.isDir()) {
1564 if (fi.suffix().toLower() == "mp4") {
1565 QString file2 = fi.path() + "/" + fi.completeBaseName() + ".m4a";
1566 //qDebug("Core::startMplayer: file2: %s", file2.toUtf8().constData());
1567 if (!QFile::exists(file2)) {
1568 // Check for upper case
1569 file2 = fi.path() + "/" + fi.completeBaseName() + ".M4A";
1570 }
1571 if (QFile::exists(file2)) {
1572 qDebug("Core::startMplayer: found %s, so it will be used as audio file", file2.toUtf8().constData());
1573 mset.external_audio = file2;
1574 }
1575 }
1576 }
1577 }
1578
1579
1580 bool screenshot_enabled = ( (pref->use_screenshot) &&
1581 (!pref->screenshot_directory.isEmpty()) &&
1582 (QFileInfo(pref->screenshot_directory).isDir()) );
1583
1584 proc->clearArguments();
1585
1586 // Set the screenshot directory
1587 /* deleted (done later) */
1588
1589 // Use absolute path, otherwise after changing to the screenshot directory
1590 // the mplayer path might not be found if it's a relative path
1591 // (seems to be necessary only for linux)
1592 QString mplayer_bin = pref->mplayer_bin;
1593 QFileInfo fi(mplayer_bin);
1594 if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
1595 mplayer_bin = fi.absoluteFilePath();
1596 }
1597
1598#ifdef MPLAYER2_SUPPORT
1599 if (fi.baseName().toLower() == "mplayer2") {
1600 if (!pref->mplayer_is_mplayer2) {
1601 qDebug("Core::startMplayer: this seems mplayer2");
1602 pref->mplayer_is_mplayer2 = true;
1603 }
1604 }
1605#endif
1606
1607 proc->setExecutable(mplayer_bin);
1608 proc->setFixedOptions();
1609
1610#ifdef LOG_MPLAYER
1611 if (pref->verbose_log) {
1612 proc->setOption("verbose");
1613 }
1614#endif
1615
1616 if (pref->fullscreen && pref->use_mplayer_window) {
1617 proc->setOption("fs", true);
1618 } else {
1619 // No mplayer fullscreen mode
1620 proc->setOption("fs", false);
1621 }
1622
1623#if !ALLOW_DEMUXER_CODEC_CHANGE
1624 if (pref->use_lavf_demuxer) {
1625 proc->setOption("demuxer", "lavf");
1626 }
1627#else
1628 // Demuxer and audio and video codecs:
1629 if (!mset.forced_demuxer.isEmpty()) {
1630 proc->setOption("demuxer", mset.forced_demuxer);
1631 }
1632 if (!mset.forced_audio_codec.isEmpty()) {
1633 proc->setOption("ac", mset.forced_audio_codec);
1634 }
1635 if (!mset.forced_video_codec.isEmpty()) {
1636 proc->setOption("vc", mset.forced_video_codec);
1637 }
1638 else
1639#endif
1640 {
1641 #ifndef Q_OS_WIN
1642 /* if (pref->vo.startsWith("x11")) { */ // My card doesn't support vdpau, I use x11 to test
1643 if (pref->vo.startsWith("vdpau")) {
1644 QString c;
1645 if (pref->vdpau.ffh264vdpau) c += "ffh264vdpau,";
1646 if (pref->vdpau.ffmpeg12vdpau) c += "ffmpeg12vdpau,";
1647 if (pref->vdpau.ffwmv3vdpau) c += "ffwmv3vdpau,";
1648 if (pref->vdpau.ffvc1vdpau) c += "ffvc1vdpau,";
1649 if (pref->vdpau.ffodivxvdpau) c += "ffodivxvdpau,";
1650 if (!c.isEmpty()) {
1651 proc->setOption("vc", c);
1652 }
1653 }
1654 else {
1655 #endif
1656 if (pref->coreavc) {
1657 proc->setOption("vc", "coreserve,");
1658 }
1659 #ifndef Q_OS_WIN
1660 }
1661 #endif
1662 }
1663
1664 if (pref->use_hwac3) {
1665 proc->setOption("afm", "hwac3");
1666 }
1667
1668
1669 if (proc->isMPlayer()) {
1670 // MPlayer
1671 QString lavdopts;
1672
1673 if ( (pref->h264_skip_loop_filter == Preferences::LoopDisabled) ||
1674 ((pref->h264_skip_loop_filter == Preferences::LoopDisabledOnHD) &&
1675 (mset.is264andHD)) )
1676 {
1677 if (!lavdopts.isEmpty()) lavdopts += ":";
1678 lavdopts += "skiploopfilter=all";
1679 }
1680
1681 if (pref->threads > 1) {
1682 if (!lavdopts.isEmpty()) lavdopts += ":";
1683 lavdopts += "threads=" + QString::number(pref->threads);
1684 }
1685
1686 if (!lavdopts.isEmpty()) {
1687 proc->setOption("lavdopts", lavdopts);
1688 }
1689 }
1690 else {
1691 // MPV
1692 if ( (pref->h264_skip_loop_filter == Preferences::LoopDisabled) ||
1693 ((pref->h264_skip_loop_filter == Preferences::LoopDisabledOnHD) &&
1694 (mset.is264andHD)) )
1695 {
1696 proc->setOption("skiploopfilter");
1697 }
1698
1699 if (pref->threads > 1) {
1700 proc->setOption("threads", QString::number(pref->threads));
1701 }
1702 }
1703
1704 if (!pref->hwdec.isEmpty()) proc->setOption("hwdec", pref->hwdec);
1705
1706 proc->setOption("sub-fuzziness", pref->subfuzziness);
1707
1708 if (!pref->vo.isEmpty()) {
1709 QString vo = pref->vo;
1710 if (!vo.endsWith(",")) vo += ",";
1711 proc->setOption("vo", vo);
1712 }
1713 #ifdef Q_OS_WIN
1714 else {
1715 if (proc->isMPlayer() && QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) {
1716 proc->setOption("vo", "direct3d,");
1717 }
1718 }
1719 #endif
1720
1721#if USE_ADAPTER
1722 if (pref->adapter > -1) {
1723 proc->setOption("adapter", QString::number(pref->adapter));
1724 }
1725#endif
1726
1727 if (!pref->ao.isEmpty()) {
1728 QString ao = pref->ao;
1729 if (!ao.endsWith(",")) ao += ",";
1730 proc->setOption("ao", ao);
1731 }
1732
1733#if !defined(Q_OS_WIN) && !defined(Q_OS_OS2)
1734 if (pref->vo.startsWith("x11")) {
1735 proc->setOption("zoom");
1736 }
1737#endif
1738
1739 // Performance options
1740 #ifdef Q_OS_WIN
1741 QString p;
1742 int app_p = NORMAL_PRIORITY_CLASS;
1743 switch (pref->priority) {
1744 case Preferences::Realtime: p = "realtime";
1745 app_p = REALTIME_PRIORITY_CLASS;
1746 break;
1747 case Preferences::High: p = "high";
1748 app_p = REALTIME_PRIORITY_CLASS;
1749 break;
1750 case Preferences::AboveNormal: p = "abovenormal";
1751 app_p = HIGH_PRIORITY_CLASS;
1752 break;
1753 case Preferences::Normal: p = "normal";
1754 app_p = ABOVE_NORMAL_PRIORITY_CLASS;
1755 break;
1756 case Preferences::BelowNormal: p = "belownormal"; break;
1757 case Preferences::Idle: p = "idle"; break;
1758 default: p = "normal";
1759 }
1760 proc->setOption("priority", p);
1761 /*
1762 SetPriorityClass(GetCurrentProcess(), app_p);
1763 qDebug("Core::startMplayer: priority of smplayer process set to %d", app_p);
1764 */
1765 #endif
1766
1767 if (pref->frame_drop && pref->hard_frame_drop) {
1768 proc->setOption("framedrop", "decoder+vo");
1769 }
1770 else
1771 if (pref->frame_drop) {
1772 proc->setOption("framedrop", "vo");
1773 }
1774 else
1775 if (pref->hard_frame_drop) {
1776 proc->setOption("framedrop", "decoder");
1777 }
1778
1779 if (pref->autosync) {
1780 proc->setOption("autosync", QString::number(pref->autosync_factor));
1781 }
1782
1783 if (pref->use_mc) {
1784 proc->setOption("mc", QString::number(pref->mc_value));
1785 }
1786
1787 proc->setOption("dr", pref->use_direct_rendering);
1788 proc->setOption("double", pref->use_double_buffer);
1789
1790#ifdef Q_WS_X11
1791 proc->setOption("stop-xscreensaver", pref->disable_screensaver);
1792#endif
1793
1794 if (!pref->use_mplayer_window) {
1795 proc->disableInput();
1796 proc->setOption("keepaspect", false);
1797
1798#if defined(Q_OS_OS2)
1799 #define WINIDFROMHWND(hwnd) ( ( hwnd ) - 0x80000000UL )
1800 proc->setOption("wid", QString::number( WINIDFROMHWND( (int) mplayerwindow->videoLayer()->winId() ) ));
1801#else
1802 proc->setOption("wid", QString::number( (qint64) mplayerwindow->videoLayer()->winId() ) );
1803#endif
1804
1805#if USE_COLORKEY
1806 #if defined(Q_OS_WIN) || defined(Q_OS_OS2)
1807 if ((pref->vo.startsWith("directx")) || (pref->vo.startsWith("kva")) || (pref->vo.isEmpty())) {
1808 proc->setOption("colorkey", ColorUtils::colorToRGB(pref->color_key));
1809 } else {
1810 #endif
1811 /*
1812 qDebug("Core::startMplayer: * not using -colorkey for %s", pref->vo.toUtf8().data());
1813 qDebug("Core::startMplayer: * report if you can't see the video");
1814 */
1815 #if defined(Q_OS_WIN) || defined(Q_OS_OS2)
1816 }
1817 #endif
1818#endif
1819
1820 // Square pixels
1821 proc->setOption("monitorpixelaspect", "1");
1822 } else {
1823 // no -wid
1824 proc->setOption("keepaspect", true);
1825 if (!pref->monitor_aspect.isEmpty()) {
1826 proc->setOption("monitoraspect", pref->monitor_aspect);
1827 }
1828 }
1829
1830 // OSD
1831 proc->setOption("osd-scale", proc->isMPlayer() ? pref->subfont_osd_scale : pref->osd_scale);
1832
1833 // Subtitles fonts
1834 if ((pref->use_ass_subtitles) && (pref->freetype_support)) {
1835 // ASS:
1836 proc->setOption("ass");
1837 proc->setOption("embeddedfonts");
1838
1839 proc->setOption("ass-line-spacing", QString::number(pref->ass_line_spacing));
1840
1841 proc->setOption("ass-font-scale", QString::number(mset.sub_scale_ass));
1842
1843#if !defined(Q_OS_OS2)
1844 #ifdef MPLAYER2_SUPPORT
1845 if (!pref->mplayer_is_mplayer2)
1846 #endif
1847 {
1848 proc->setOption("flip-hebrew",false); // It seems to be necessary to display arabic subtitles correctly when using -ass
1849 }
1850#endif
1851
1852 if (pref->enable_ass_styles) {
1853 QString ass_force_style;
1854 if (!pref->user_forced_ass_style.isEmpty()) {
1855 ass_force_style = pref->user_forced_ass_style;
1856 } else {
1857 ass_force_style = pref->ass_styles.toString();
1858 }
1859
1860 if (proc->isMPV()) {
1861 // MPV
1862 proc->setSubStyles(pref->ass_styles);
1863 if (pref->force_ass_styles) {
1864 proc->setOption("ass-force-style", ass_force_style);
1865 }
1866 } else {
1867 // MPlayer
1868 if (!pref->force_ass_styles) {
1869 proc->setSubStyles(pref->ass_styles, Paths::subtitleStyleFile());
1870 } else {
1871 proc->setOption("ass-force-style", ass_force_style);
1872 }
1873 }
1874 }
1875
1876 // Use the same font for OSD
1877 // deleted
1878
1879 // Set the size of OSD
1880 // deleted
1881 } else {
1882 // NO ASS:
1883 if (pref->freetype_support) proc->setOption("noass");
1884 proc->setOption("subfont-text-scale", QString::number(mset.sub_scale));
1885 }
1886
1887 // Subtitle encoding
1888 {
1889 QString encoding;
1890 if ( (pref->use_enca) && (!pref->enca_lang.isEmpty()) ) {
1891 encoding = "enca:"+ pref->enca_lang;
1892 if (!pref->subcp.isEmpty()) {
1893 encoding += ":"+ pref->subcp;
1894 }
1895 }
1896 else
1897 if (!pref->subcp.isEmpty()) {
1898 encoding = pref->subcp;
1899 }
1900
1901 if (!encoding.isEmpty()) {
1902 proc->setOption("subcp", encoding);
1903 }
1904 }
1905
1906 if (mset.closed_caption_channel > 0) {
1907 proc->setOption("subcc", QString::number(mset.closed_caption_channel));
1908 }
1909
1910 if (pref->use_forced_subs_only) {
1911 proc->setOption("forcedsubsonly");
1912 }
1913
1914#if PROGRAM_SWITCH
1915 if ( (mset.current_program_id != MediaSettings::NoneSelected) /*&&
1916 (mset.current_video_id == MediaSettings::NoneSelected) &&
1917 (mset.current_audio_id == MediaSettings::NoneSelected)*/ )
1918 {
1919 proc->setOption("tsprog", QString::number(mset.current_program_id));
1920 }
1921 // Don't set video and audio track if using -tsprog
1922 else {
1923#endif
1924
1925#if 1
1926 if (mset.current_video_id != MediaSettings::NoneSelected) {
1927 proc->setOption("vid", QString::number(mset.current_video_id));
1928 }
1929
1930 if (mset.external_audio.isEmpty()) {
1931 if (mset.current_audio_id != MediaSettings::NoneSelected) {
1932 // Workaround for MPlayer bug #1321 (http://bugzilla.mplayerhq.hu/show_bug.cgi?id=1321)
1933 if (mdat.audios.numItems() != 1) {
1934 proc->setOption("aid", QString::number(mset.current_audio_id));
1935 }
1936 }
1937 }
1938#endif
1939
1940#if PROGRAM_SWITCH
1941 }
1942#endif
1943
1944 if (!initial_subtitle.isEmpty()) {
1945 mset.external_subtitles = initial_subtitle;
1946 initial_subtitle = "";
1947 just_loaded_external_subs = true; // Big ugly hack :(
1948 }
1949 if (!mset.external_subtitles.isEmpty()) {
1950 bool is_idx = (QFileInfo(mset.external_subtitles).suffix().toLower()=="idx");
1951 if (proc->isMPV()) is_idx = false; // Hack to ignore the idx extension with mpv
1952
1953 if (is_idx) {
1954 // sub/idx subtitles
1955 QFileInfo fi;
1956
1957 #ifdef Q_OS_WIN
1958 if (pref->use_short_pathnames)
1959 fi.setFile(Helper::shortPathName(mset.external_subtitles));
1960 else
1961 #endif
1962 fi.setFile(mset.external_subtitles);
1963
1964 QString s = fi.path() +"/"+ fi.completeBaseName();
1965 qDebug("Core::startMplayer: subtitle file without extension: '%s'", s.toUtf8().data());
1966 proc->setOption("vobsub", s);
1967 } else {
1968 #ifdef Q_OS_WIN
1969 if (pref->use_short_pathnames)
1970 proc->setOption("sub", Helper::shortPathName(mset.external_subtitles));
1971 else
1972 #endif
1973 {
1974 proc->setOption("sub", mset.external_subtitles);
1975 }
1976 }
1977 if (mset.external_subtitles_fps != MediaSettings::SFPS_None) {
1978 QString fps;
1979 switch (mset.external_subtitles_fps) {
1980 case MediaSettings::SFPS_23: fps = "23"; break;
1981 case MediaSettings::SFPS_24: fps = "24"; break;
1982 case MediaSettings::SFPS_25: fps = "25"; break;
1983 case MediaSettings::SFPS_30: fps = "30"; break;
1984 case MediaSettings::SFPS_23976: fps = "24000/1001"; break;
1985 case MediaSettings::SFPS_29970: fps = "30000/1001"; break;
1986 default: fps = "25";
1987 }
1988 proc->setOption("subfps", fps);
1989 }
1990 }
1991
1992 if (!mset.external_audio.isEmpty()) {
1993 #ifdef Q_OS_WIN
1994 if (pref->use_short_pathnames)
1995 proc->setOption("audiofile", Helper::shortPathName(mset.external_audio));
1996 else
1997 #endif
1998 {
1999 proc->setOption("audiofile", mset.external_audio);
2000 }
2001 }
2002
2003 proc->setOption("subpos", QString::number(mset.sub_pos));
2004
2005 if (mset.audio_delay != 0) {
2006 proc->setOption("delay", QString::number((double) mset.audio_delay/1000));
2007 }
2008
2009 if (mset.sub_delay != 0) {
2010 proc->setOption("subdelay", QString::number((double) mset.sub_delay/1000));
2011 }
2012
2013 // Contrast, brightness...
2014 if (pref->change_video_equalizer_on_startup) {
2015 if (mset.contrast != 0) {
2016 proc->setOption("contrast", QString::number(mset.contrast));
2017 }
2018
2019 if (mset.brightness != 0) {
2020 proc->setOption("brightness", QString::number(mset.brightness));
2021 }
2022
2023 if (mset.hue != 0) {
2024 proc->setOption("hue", QString::number(mset.hue));
2025 }
2026
2027 if (mset.saturation != 0) {
2028 proc->setOption("saturation", QString::number(mset.saturation));
2029 }
2030
2031 if (mset.gamma != 0) {
2032 proc->setOption("gamma", QString::number(mset.gamma));
2033 }
2034 }
2035
2036
2037 if (pref->mplayer_additional_options.contains("-volume")) {
2038 qDebug("Core::startMplayer: don't set volume since -volume is used");
2039 } else {
2040 int vol = (pref->global_volume ? pref->volume : mset.volume);
2041 if (proc->isMPV()) {
2042 vol = adjustVolume(vol, pref->use_soft_vol ? pref->softvol_max : 100);
2043 }
2044 proc->setOption("volume", QString::number(vol));
2045 }
2046
2047 if (pref->mute) {
2048 proc->setOption("mute");
2049 }
2050
2051
2052 if (mdat.type==TYPE_DVD) {
2053 if (!dvd_folder.isEmpty()) {
2054 #ifdef Q_OS_WIN
2055 if (pref->use_short_pathnames) {
2056 proc->setOption("dvd-device", Helper::shortPathName(dvd_folder));
2057 }
2058 else
2059 #endif
2060 proc->setOption("dvd-device", dvd_folder);
2061 } else {
2062 qWarning("Core::startMplayer: dvd device is empty!");
2063 }
2064 }
2065
2066 if ((mdat.type==TYPE_VCD) || (mdat.type==TYPE_AUDIO_CD)) {
2067 if (!pref->cdrom_device.isEmpty()) {
2068 proc->setOption("cdrom-device", pref->cdrom_device);
2069 }
2070 }
2071
2072 if (mset.current_angle_id > 0) {
2073 proc->setOption("dvdangle", QString::number( mset.current_angle_id));
2074 }
2075
2076
2077 int cache = 0;
2078 switch (mdat.type) {
2079 case TYPE_FILE : cache = pref->cache_for_files; break;
2080 case TYPE_DVD : cache = pref->cache_for_dvds;
2081 #if DVDNAV_SUPPORT
2082 if (file.startsWith("dvdnav:")) cache = 0;
2083 #endif
2084 break;
2085 case TYPE_STREAM : cache = pref->cache_for_streams; break;
2086 case TYPE_VCD : cache = pref->cache_for_vcds; break;
2087 case TYPE_AUDIO_CD : cache = pref->cache_for_audiocds; break;
2088#ifdef TV_SUPPORT
2089 case TYPE_TV : cache = pref->cache_for_tv; break;
2090#endif
2091#ifdef BLURAY_SUPPORT
2092 case TYPE_BLURAY : cache = pref->cache_for_dvds; break; // FIXME: use cache for bluray?
2093#endif
2094 default: cache = 0;
2095 }
2096
2097 if (pref->cache_auto) {
2098 proc->setOption("cache_auto");
2099 } else {
2100 proc->setOption("cache", QString::number(cache));
2101 }
2102
2103 if (mset.speed != 1.0) {
2104 proc->setOption("speed", QString::number(mset.speed));
2105 }
2106
2107 if (mdat.type != TYPE_TV) {
2108 // Play A - B
2109 if ((mset.A_marker > -1) && (mset.B_marker > mset.A_marker)) {
2110 if (proc->isMPV()) {
2111 if (mset.loop) {
2112 proc->setOption("ab-loop-a", QString::number(mset.A_marker));
2113 proc->setOption("ab-loop-b", QString::number(mset.B_marker));
2114 }
2115 } else {
2116 proc->setOption("ss", QString::number(mset.A_marker));
2117 proc->setOption("endpos", QString::number(mset.B_marker - mset.A_marker));
2118 }
2119 }
2120 else
2121 // If seek < 5 it's better to allow the video to start from the beginning
2122 if ((seek >= 5) && (!mset.loop)) {
2123 proc->setOption("ss", QString::number(seek));
2124 }
2125 }
2126
2127 // Enable the OSD later, to avoid a lot of messages to be
2128 // printed on startup
2129 proc->setOption("osdlevel", "0");
2130
2131 if (pref->use_idx) {
2132 proc->setOption("idx");
2133 }
2134
2135 if (mdat.type == TYPE_STREAM) {
2136 if (pref->prefer_ipv4) {
2137 proc->setOption("prefer-ipv4");
2138 } else {
2139 proc->setOption("prefer-ipv6");
2140 }
2141 }
2142
2143 if (pref->use_correct_pts != Preferences::Detect) {
2144 proc->setOption("correct-pts", (pref->use_correct_pts == Preferences::Enabled));
2145 }
2146
2147 bool force_noslices = false;
2148
2149#ifndef Q_OS_WIN
2150 if (proc->isMPlayer()) {
2151 if ((pref->vdpau.disable_video_filters) && (pref->vo.startsWith("vdpau"))) {
2152 qDebug("Core::startMplayer: using vdpau, video filters are ignored");
2153 goto end_video_filters;
2154 }
2155 } else {
2156 // MPV
2157 if (!pref->hwdec.isEmpty() && pref->hwdec != "no") {
2158 qDebug("Core::startMplayer: hardware decoding is enabled. The video filters will be ignored");
2159 goto end_video_filters;
2160 }
2161 }
2162#endif
2163
2164 // Video filters:
2165 // Phase
2166 if (mset.phase_filter) {
2167 proc->addVF("phase", "A");
2168 }
2169
2170 // Deinterlace
2171 if (mset.current_deinterlacer != MediaSettings::NoDeinterlace) {
2172 switch (mset.current_deinterlacer) {
2173 case MediaSettings::L5: proc->addVF("l5"); break;
2174 case MediaSettings::Yadif: proc->addVF("yadif"); break;
2175 case MediaSettings::LB: proc->addVF("lb"); break;
2176 case MediaSettings::Yadif_1: proc->addVF("yadif", "1"); break;
2177 case MediaSettings::Kerndeint: proc->addVF("kerndeint", "5"); break;
2178 }
2179 }
2180
2181 // 3D stereo
2182 if (mset.stereo3d_in != "none" && !mset.stereo3d_out.isEmpty()) {
2183 proc->addStereo3DFilter(mset.stereo3d_in, mset.stereo3d_out);
2184 }
2185
2186 // Denoise
2187 if (mset.current_denoiser != MediaSettings::NoDenoise) {
2188 if (mset.current_denoiser==MediaSettings::DenoiseSoft) {
2189 proc->addVF("hqdn3d", pref->filters->item("denoise_soft").options());
2190 } else {
2191 proc->addVF("hqdn3d", pref->filters->item("denoise_normal").options());
2192 }
2193 }
2194
2195 // Unsharp
2196 if (mset.current_unsharp != 0) {
2197 if (mset.current_unsharp == 1) {
2198 proc->addVF("blur", pref->filters->item("blur").options());
2199 } else {
2200 proc->addVF("sharpen", pref->filters->item("sharpen").options());
2201 }
2202 }
2203
2204 // Deblock
2205 if (mset.deblock_filter) {
2206 proc->addVF("deblock", pref->filters->item("deblock").options());
2207 }
2208
2209 // Dering
2210 if (mset.dering_filter) {
2211 proc->addVF("dering");
2212 }
2213
2214 // Gradfun
2215 if (mset.gradfun_filter) {
2216 proc->addVF("gradfun", pref->filters->item("gradfun").options());
2217 }
2218
2219 // Upscale
2220 if (mset.upscaling_filter) {
2221 int width = DesktopInfo::desktop_size(mplayerwindow).width();
2222 proc->setOption("sws", "9");
2223 proc->addVF("scale", QString::number(width) + ":-2");
2224 }
2225
2226 // Addnoise
2227 if (mset.noise_filter) {
2228 proc->addVF("noise", pref->filters->item("noise").options());
2229 }
2230
2231 // Postprocessing
2232 if (mset.postprocessing_filter) {
2233 proc->addVF("postprocessing");
2234 proc->setOption("autoq", QString::number(pref->autoq));
2235 }
2236
2237
2238 // Letterbox (expand)
2239 if ((mset.add_letterbox) || (pref->fullscreen && pref->add_blackborders_on_fullscreen)) {
2240 proc->addVF("expand", QString("aspect=%1").arg( DesktopInfo::desktop_aspectRatio(mplayerwindow)));
2241 }
2242
2243 // Software equalizer
2244 if ( (pref->use_soft_video_eq) ) {
2245 proc->addVF("eq2");
2246 proc->addVF("hue");
2247 if ( (pref->vo == "gl") || (pref->vo == "gl2") || (pref->vo == "gl_tiled")
2248#ifdef Q_OS_WIN
2249 || (pref->vo == "directx:noaccel")
2250#endif
2251 )
2252 {
2253 proc->addVF("scale");
2254 }
2255 }
2256
2257 // Additional video filters, supplied by user
2258 // File
2259 if ( !mset.mplayer_additional_video_filters.isEmpty() ) {
2260 proc->setOption("vf-add", mset.mplayer_additional_video_filters);
2261 }
2262 // Global
2263 if ( !pref->mplayer_additional_video_filters.isEmpty() ) {
2264 proc->setOption("vf-add", pref->mplayer_additional_video_filters);
2265 }
2266
2267 // Filters for subtitles on screenshots
2268 if ((screenshot_enabled) && (pref->subtitles_on_screenshots))
2269 {
2270 if (pref->use_ass_subtitles) {
2271 proc->addVF("subs_on_screenshots", "ass");
2272 } else {
2273 proc->addVF("subs_on_screenshots");
2274 force_noslices = true;
2275 }
2276 }
2277
2278 // Rotate
2279 if (mset.rotate != MediaSettings::NoRotate) {
2280 proc->addVF("rotate", QString::number(mset.rotate));
2281 }
2282
2283 // Flip
2284 if (mset.flip) {
2285 proc->addVF("flip");
2286 }
2287
2288 // Mirror
2289 if (mset.mirror) {
2290 proc->addVF("mirror");
2291 }
2292
2293 // Screenshots
2294 #ifdef MPLAYER_SUPPORT
2295 if (screenshot_enabled && proc->isMPlayer()) {
2296 QString dir = pref->screenshot_directory;
2297 #ifdef Q_OS_WIN
2298 if (pref->use_short_pathnames) dir = Helper::shortPathName(pref->screenshot_directory);
2299 #endif
2300 proc->enableScreenshots(dir);
2301 }
2302 #endif
2303
2304#ifndef Q_OS_WIN
2305 end_video_filters:
2306#endif
2307
2308 #ifdef MPV_SUPPORT
2309 if (screenshot_enabled && proc->isMPV()) {
2310 QString dir = pref->screenshot_directory;
2311 #ifdef Q_OS_WIN
2312 if (pref->use_short_pathnames) dir = Helper::shortPathName(pref->screenshot_directory);
2313 #endif
2314 proc->enableScreenshots(dir, pref->screenshot_template, pref->screenshot_format);
2315 }
2316 #endif
2317
2318 // slices
2319 if ((pref->use_slices) && (!force_noslices)) {
2320 proc->setOption("slices", true);
2321 } else {
2322 proc->setOption("slices", false);
2323 }
2324
2325
2326 // Audio channels
2327 if (mset.audio_use_channels != 0) {
2328 proc->setOption("channels", QString::number(mset.audio_use_channels));
2329 }
2330
2331 if (!pref->use_hwac3) {
2332
2333 // Audio filters
2334 #ifdef MPLAYER_SUPPORT
2335 if (mset.karaoke_filter) {
2336 proc->addAF("karaoke");
2337 }
2338 #endif
2339
2340 // Stereo mode
2341 if (mset.stereo_mode != 0) {
2342 switch (mset.stereo_mode) {
2343 case MediaSettings::Left: proc->addAF("channels", "2:2:0:1:0:0"); break;
2344 case MediaSettings::Right: proc->addAF("channels", "2:2:1:0:1:1"); break;
2345 case MediaSettings::Mono: proc->addAF("pan", "1:0.5:0.5"); break;
2346 case MediaSettings::Reverse: proc->addAF("channels", "2:2:0:1:1:0"); break;
2347 }
2348 }
2349
2350 if (mset.extrastereo_filter) {
2351 proc->addAF("extrastereo");
2352 }
2353
2354 if (mset.volnorm_filter) {
2355 proc->addAF("volnorm", pref->filters->item("volnorm").options());
2356 }
2357
2358 if (proc->isMPlayer()) {
2359 bool use_scaletempo = (pref->use_scaletempo == Preferences::Enabled);
2360 if (pref->use_scaletempo == Preferences::Detect) {
2361 use_scaletempo = (MplayerVersion::isMplayerAtLeast(24924));
2362 }
2363 if (use_scaletempo) {
2364 proc->addAF("scaletempo");
2365 }
2366 } else {
2367 // MPV
2368 proc->setOption("scaletempo", pref->use_scaletempo != Preferences::Disabled);
2369 }
2370
2371 // Audio equalizer
2372 if (pref->use_audio_equalizer) {
2373 AudioEqualizerList l = pref->global_audio_equalizer ? pref->audio_equalizer : mset.audio_equalizer;
2374 proc->addAF("equalizer", Helper::equalizerListToString(l));
2375 }
2376
2377 // Additional audio filters, supplied by user
2378 // File
2379 if ( !pref->mplayer_additional_audio_filters.isEmpty() ) {
2380 proc->setOption("af-add", pref->mplayer_additional_audio_filters);
2381 }
2382 // Global
2383 if ( !mset.mplayer_additional_audio_filters.isEmpty() ) {
2384 proc->setOption("af-add", mset.mplayer_additional_audio_filters);
2385 }
2386 } else {
2387 // Don't use audio filters if using the S/PDIF output
2388 qDebug("Core::startMplayer: audio filters are disabled when using the S/PDIF output!");
2389 }
2390
2391 if (pref->use_soft_vol) {
2392 proc->setOption("softvol", QString::number(pref->softvol_max));
2393 } else {
2394 proc->setOption("softvol", "off");
2395 }
2396
2397#ifdef MPV_SUPPORT
2398 if (mdat.type == TYPE_STREAM) {
2399 if (pref->streaming_type == Preferences::StreamingAuto) {
2400 bool is_youtube = false;
2401 #ifdef YOUTUBE_SUPPORT
2402 if (PREF_YT_ENABLED) is_youtube = (file == yt->latestPreferredUrl());
2403 #endif
2404 qDebug() << "Core::startMplayer: is_youtube:" << is_youtube;
2405 bool enable_sites = !is_youtube;
2406
2407 if (!is_youtube) {
2408 // Check if the URL contains a media extension
2409 QString extension = Extensions::extensionFromUrl(file);
2410 qDebug() << "Core::startMplayer: URL extension:" << extension;
2411 Extensions e;
2412 if (e.allPlayable().contains(extension)) {
2413 qDebug() << "Core::startMplayer: extension found in URL";
2414 enable_sites = false;
2415 }
2416 }
2417 qDebug() << "Core::startMplayer: enable_sites:" << enable_sites;
2418 proc->setOption("enable_streaming_sites_support", enable_sites);
2419 } else {
2420 proc->setOption("enable_streaming_sites_support", pref->streaming_type == Preferences::StreamingYTDL);
2421 }
2422 }
2423#endif
2424
2425#if defined(TV_SUPPORT) && !defined(Q_OS_WIN)
2426 if (proc->isMPV() && file.startsWith("dvb:")) {
2427 QString channels_file = TVList::findChannelsFile();
2428 qDebug("Core::startMplayer: channels_file: %s", channels_file.toUtf8().constData());
2429 if (!channels_file.isEmpty()) proc->setChannelsFile(channels_file);
2430 }
2431#endif
2432
2433#ifdef CAPTURE_STREAM
2434 // Set the capture directory
2435 proc->setCaptureDirectory(pref->capture_directory);
2436#endif
2437
2438 // Load edl file
2439 if (pref->use_edl_files) {
2440 QString edl_f;
2441 QFileInfo f(file);
2442 QString basename = f.path() + "/" + f.completeBaseName();
2443
2444 //qDebug("Core::startMplayer: file basename: '%s'", basename.toUtf8().data());
2445
2446 if (QFile::exists(basename+".edl"))
2447 edl_f = basename+".edl";
2448 else
2449 if (QFile::exists(basename+".EDL"))
2450 edl_f = basename+".EDL";
2451
2452 qDebug("Core::startMplayer: edl file: '%s'", edl_f.toUtf8().data());
2453 if (!edl_f.isEmpty()) {
2454 proc->setOption("edl", edl_f);
2455 }
2456 }
2457
2458 // Additional options supplied by the user
2459 // File
2460 if (!mset.mplayer_additional_options.isEmpty()) {
2461 QStringList args = MyProcess::splitArguments(mset.mplayer_additional_options);
2462 for (int n = 0; n < args.count(); n++) {
2463 QString arg = args[n].simplified();
2464 if (!arg.isEmpty()) {
2465 proc->addUserOption(arg);
2466 }
2467 }
2468 }
2469
2470 // Global
2471 if (!pref->mplayer_additional_options.isEmpty()) {
2472 QString additional_options = pref->mplayer_additional_options;
2473 #ifdef MPLAYER2_SUPPORT
2474 // mplayer2 doesn't support -fontconfig and -nofontconfig
2475 if (pref->mplayer_is_mplayer2) {
2476 additional_options.replace("-fontconfig", "");
2477 additional_options.replace("-nofontconfig", "");
2478 }
2479 #endif
2480 QStringList args = MyProcess::splitArguments(additional_options);
2481 for (int n = 0; n < args.count(); n++) {
2482 QString arg = args[n].simplified();
2483 if (!arg.isEmpty()) {
2484 qDebug("arg %d: %s", n, arg.toUtf8().constData());
2485 proc->addUserOption(arg);
2486 }
2487 }
2488
2489 }
2490
2491 // Last checks for the file
2492
2493 // Open https URLs with ffmpeg
2494 #if 0
2495 // It doesn't seem necessary anymore
2496 if (proc->isMPlayer() && file.startsWith("https")) {
2497 file = "ffmpeg://" + file;
2498 }
2499 #endif
2500
2501#if DVDNAV_SUPPORT
2502 if (proc->isMPV() && file.startsWith("dvdnav:")) {
2503 // Hack to open the DVD menu with MPV
2504 file = "dvd://menu";
2505 }
2506#endif
2507
2508#ifdef Q_OS_WIN
2509 if (pref->use_short_pathnames) {
2510 file = Helper::shortPathName(file);
2511 }
2512#endif
2513
2514#ifdef MPLAYER_SUPPORT
2515 if (proc->isMPlayer()) {
2516 proc->setMedia(file, pref->use_playlist_option ? url_is_playlist : false);
2517 } else
2518#endif
2519 {
2520 proc->setMedia(file, false); // Don't use playlist with mpv
2521 }
2522
2523 // It seems the loop option must be after the filename
2524 if (mset.loop) {
2525 proc->setOption("loop", "0");
2526 }
2527
2528 emit aboutToStartPlaying();
2529
2530 QString commandline = proc->arguments().join(" ");
2531 qDebug("Core::startMplayer: command: '%s'", commandline.toUtf8().data());
2532
2533 //Log command
2534 QString line_for_log = commandline + "\n";
2535 emit logLineAvailable(line_for_log);
2536
2537 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2538 if ((pref->use_proxy) && (pref->proxy_type == QNetworkProxy::HttpProxy) && (!pref->proxy_host.isEmpty())) {
2539 QString proxy = QString("http://%1:%2@%3:%4").arg(pref->proxy_username).arg(pref->proxy_password).arg(pref->proxy_host).arg(pref->proxy_port);
2540 env.insert("http_proxy", proxy);
2541 }
2542 //qDebug("Core::startMplayer: env: %s", env.toStringList().join(",").toUtf8().constData());
2543 #ifdef FONTS_HACK
2544 if (!pref->use_windowsfontdir) {
2545 env.insert("FONTCONFIG_FILE", Paths::configPath() + "/fonts.conf");
2546 }
2547 #endif
2548 proc->setProcessEnvironment(env);
2549
2550 if ( !proc->start() ) {
2551 // error handling
2552 qWarning("Core::startMplayer: mplayer process didn't start");
2553 }
2554
2555}
2556
2557void Core::stopMplayer() {
2558 qDebug("Core::stopMplayer");
2559
2560 if (!proc->isRunning()) {
2561 qWarning("Core::stopMplayer: mplayer is not running!");
2562 return;
2563 }
2564
2565#ifdef Q_OS_OS2
2566 QEventLoop eventLoop;
2567
2568 connect(proc, SIGNAL(processExited()), &eventLoop, SLOT(quit()));
2569
2570 proc->quit();
2571
2572 QTimer::singleShot(5000, &eventLoop, SLOT(quit()));
2573 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2574
2575 if (proc->isRunning()) {
2576 qWarning("Core::stopMplayer: process didn't finish. Killing it...");
2577 proc->kill();
2578 }
2579#else
2580 proc->quit();
2581
2582 qDebug("Core::stopMplayer: Waiting mplayer to finish...");
2583 if (!proc->waitForFinished(pref->time_to_kill_mplayer)) {
2584 qWarning("Core::stopMplayer: process didn't finish. Killing it...");
2585 proc->kill();
2586 }
2587#endif
2588
2589 qDebug("Core::stopMplayer: Finished. (I hope)");
2590}
2591
2592
2593void Core::goToSec( double sec ) {
2594 qDebug("Core::goToSec: %f", sec);
2595
2596 if (sec < 0) sec = 0;
2597 if (sec > mdat.duration ) sec = mdat.duration - 20;
2598 seek_cmd(sec, 2);
2599}
2600
2601
2602void Core::seek(int secs) {
2603 qDebug("Core::seek: %d", secs);
2604 if ( (proc->isRunning()) && (secs!=0) ) {
2605 seek_cmd(secs, 0);
2606 }
2607}
2608
2609void Core::seek_cmd(double secs, int mode) {
2610 proc->seek(secs, mode, pref->precise_seeking);
2611}
2612
2613void Core::sforward() {
2614 qDebug("Core::sforward");
2615 seek( pref->seeking1 ); // +10s
2616}
2617
2618void Core::srewind() {
2619 qDebug("Core::srewind");
2620 seek( -pref->seeking1 ); // -10s
2621}
2622
2623
2624void Core::forward() {
2625 qDebug("Core::forward");
2626 seek( pref->seeking2 ); // +1m
2627}
2628
2629
2630void Core::rewind() {
2631 qDebug("Core::rewind");
2632 seek( -pref->seeking2 ); // -1m
2633}
2634
2635
2636void Core::fastforward() {
2637 qDebug("Core::fastforward");
2638 seek( pref->seeking3 ); // +10m
2639}
2640
2641
2642void Core::fastrewind() {
2643 qDebug("Core::fastrewind");
2644 seek( -pref->seeking3 ); // -10m
2645}
2646
2647void Core::forward(int secs) {
2648 qDebug("Core::forward: %d", secs);
2649 seek(secs);
2650}
2651
2652void Core::rewind(int secs) {
2653 qDebug("Core::rewind: %d", secs);
2654 seek(-secs);
2655}
2656
2657#ifdef MPV_SUPPORT
2658void Core::seekToNextSub() {
2659 qDebug("Core::seekToNextSub");
2660 proc->seekSub(1);
2661}
2662
2663void Core::seekToPrevSub() {
2664 qDebug("Core::seekToPrevSub");
2665 proc->seekSub(-1);
2666}
2667#endif
2668
2669void Core::wheelUp() {
2670 qDebug("Core::wheelUp");
2671 switch (pref->wheel_function) {
2672 case Preferences::Volume : incVolume(); break;
2673 case Preferences::Zoom : incZoom(); break;
2674 case Preferences::Seeking : pref->wheel_function_seeking_reverse ? rewind( pref->seeking4 ) : forward( pref->seeking4 ); break;
2675 case Preferences::ChangeSpeed : incSpeed10(); break;
2676 default : {} // do nothing
2677 }
2678}
2679
2680void Core::wheelDown() {
2681 qDebug("Core::wheelDown");
2682 switch (pref->wheel_function) {
2683 case Preferences::Volume : decVolume(); break;
2684 case Preferences::Zoom : decZoom(); break;
2685 case Preferences::Seeking : pref->wheel_function_seeking_reverse ? forward( pref->seeking4 ) : rewind( pref->seeking4 ); break;
2686 case Preferences::ChangeSpeed : decSpeed10(); break;
2687 default : {} // do nothing
2688 }
2689}
2690
2691void Core::setAMarker() {
2692 setAMarker((int)mset.current_sec);
2693}
2694
2695void Core::setAMarker(int sec) {
2696 qDebug("Core::setAMarker: %d", sec);
2697
2698 mset.A_marker = sec;
2699 displayMessage( tr("\"A\" marker set to %1").arg(Helper::formatTime(sec)) );
2700
2701 if (proc->isMPV()) {
2702 if (mset.loop) proc->setAMarker(sec);
2703 } else {
2704 // MPlayer
2705 if (mset.B_marker > mset.A_marker) {
2706 if (proc->isRunning()) restartPlay();
2707 }
2708 }
2709
2710 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
2711}
2712
2713void Core::setBMarker() {
2714 setBMarker((int)mset.current_sec);
2715}
2716
2717void Core::setBMarker(int sec) {
2718 qDebug("Core::setBMarker: %d", sec);
2719
2720 mset.B_marker = sec;
2721 displayMessage( tr("\"B\" marker set to %1").arg(Helper::formatTime(sec)) );
2722
2723 if (proc->isMPV()) {
2724 if (mset.loop) proc->setBMarker(sec);
2725 } else {
2726 // MPlayer
2727 if ((mset.A_marker > -1) && (mset.A_marker < mset.B_marker)) {
2728 if (proc->isRunning()) restartPlay();
2729 }
2730 }
2731
2732 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
2733}
2734
2735void Core::clearABMarkers() {
2736 qDebug("Core::clearABMarkers");
2737
2738 if ((mset.A_marker != -1) || (mset.B_marker != -1)) {
2739 mset.A_marker = -1;
2740 mset.B_marker = -1;
2741 displayMessage( tr("A-B markers cleared") );
2742 if (proc->isMPV()) {
2743 proc->clearABMarkers();
2744 } else {
2745 // MPlayer
2746 if (proc->isRunning()) restartPlay();
2747 }
2748 }
2749
2750 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
2751}
2752
2753void Core::toggleRepeat() {
2754 qDebug("Core::toggleRepeat");
2755 toggleRepeat( !mset.loop );
2756}
2757
2758void Core::toggleRepeat(bool b) {
2759 qDebug("Core::toggleRepeat: %d", b);
2760 if ( mset.loop != b ) {
2761 mset.loop = b;
2762 if (MplayerVersion::isMplayerAtLeast(23747)) {
2763 // Use slave command
2764 int v = -1; // no loop
2765 if (mset.loop) v = 0; // infinite loop
2766 if (proc->isMPV()) {
2767 // Enable A-B markers
2768 proc->clearABMarkers();
2769 if (b) {
2770 if (mset.A_marker > -1) proc->setAMarker(mset.A_marker);
2771 if (mset.B_marker > -1) proc->setBMarker(mset.B_marker);
2772 }
2773 }
2774 proc->setLoop(v);
2775 } else {
2776 // Restart mplayer
2777 if (proc->isRunning()) restartPlay();
2778 }
2779 }
2780}
2781
2782
2783// Audio filters
2784#ifdef MPLAYER_SUPPORT
2785void Core::toggleKaraoke() {
2786 toggleKaraoke( !mset.karaoke_filter );
2787}
2788
2789void Core::toggleKaraoke(bool b) {
2790 qDebug("Core::toggleKaraoke: %d", b);
2791 if (b != mset.karaoke_filter) {
2792 mset.karaoke_filter = b;
2793 if (MplayerVersion::isMplayerAtLeast(31030)) {
2794 // Change filter without restarting
2795 proc->enableKaraoke(b);
2796 } else {
2797 restartPlay();
2798 }
2799 }
2800}
2801#endif
2802
2803void Core::toggleExtrastereo() {
2804 toggleExtrastereo( !mset.extrastereo_filter );
2805}
2806
2807void Core::toggleExtrastereo(bool b) {
2808 qDebug("Core::toggleExtrastereo: %d", b);
2809 if (b != mset.extrastereo_filter) {
2810 mset.extrastereo_filter = b;
2811 if (MplayerVersion::isMplayerAtLeast(31030)) {
2812 // Change filter without restarting
2813 proc->enableExtrastereo(b);
2814 } else {
2815 restartPlay();
2816 }
2817 }
2818}
2819
2820void Core::toggleVolnorm() {
2821 toggleVolnorm( !mset.volnorm_filter );
2822}
2823
2824void Core::toggleVolnorm(bool b) {
2825 qDebug("Core::toggleVolnorm: %d", b);
2826 if (b != mset.volnorm_filter) {
2827 mset.volnorm_filter = b;
2828 if (MplayerVersion::isMplayerAtLeast(31030)) {
2829 // Change filter without restarting
2830 QString f = pref->filters->item("volnorm").filter();
2831 proc->enableVolnorm(b, pref->filters->item("volnorm").options());
2832 } else {
2833 restartPlay();
2834 }
2835 }
2836}
2837
2838void Core::setAudioChannels(int channels) {
2839 qDebug("Core::setAudioChannels:%d", channels);
2840 if (channels != mset.audio_use_channels ) {
2841 mset.audio_use_channels = channels;
2842 restartPlay();
2843 }
2844}
2845
2846void Core::setStereoMode(int mode) {
2847 qDebug("Core::setStereoMode:%d", mode);
2848 if (mode != mset.stereo_mode ) {
2849 mset.stereo_mode = mode;
2850 restartPlay();
2851 }
2852}
2853
2854
2855// Video filters
2856
2857#define CHANGE_VF(Filter, Enable, Option) \
2858 if (proc->isMPV()) { \
2859 proc->changeVF(Filter, Enable, Option); \
2860 } else { \
2861 restartPlay(); \
2862 }
2863
2864void Core::toggleFlip() {
2865 qDebug("Core::toggleFlip");
2866 toggleFlip( !mset.flip );
2867}
2868
2869void Core::toggleFlip(bool b) {
2870 qDebug("Core::toggleFlip: %d", b);
2871 if (mset.flip != b) {
2872 mset.flip = b;
2873 CHANGE_VF("flip", b, QVariant());
2874 }
2875}
2876
2877void Core::toggleMirror() {
2878 qDebug("Core::toggleMirror");
2879 toggleMirror( !mset.mirror );
2880}
2881
2882void Core::toggleMirror(bool b) {
2883 qDebug("Core::toggleMirror: %d", b);
2884 if (mset.mirror != b) {
2885 mset.mirror = b;
2886 CHANGE_VF("mirror", b, QVariant());
2887 }
2888}
2889
2890void Core::toggleAutophase() {
2891 toggleAutophase( !mset.phase_filter );
2892}
2893
2894void Core::toggleAutophase( bool b ) {
2895 qDebug("Core::toggleAutophase: %d", b);
2896 if ( b != mset.phase_filter) {
2897 mset.phase_filter = b;
2898 CHANGE_VF("phase", b, "A");
2899 }
2900}
2901
2902void Core::toggleDeblock() {
2903 toggleDeblock( !mset.deblock_filter );
2904}
2905
2906void Core::toggleDeblock(bool b) {
2907 qDebug("Core::toggleDeblock: %d", b);
2908 if ( b != mset.deblock_filter ) {
2909 mset.deblock_filter = b;
2910 CHANGE_VF("deblock", b, pref->filters->item("deblock").options());
2911 }
2912}
2913
2914void Core::toggleDering() {
2915 toggleDering( !mset.dering_filter );
2916}
2917
2918void Core::toggleDering(bool b) {
2919 qDebug("Core::toggleDering: %d", b);
2920 if ( b != mset.dering_filter) {
2921 mset.dering_filter = b;
2922 CHANGE_VF("dering", b, QVariant());
2923 }
2924}
2925
2926void Core::toggleGradfun() {
2927 toggleGradfun( !mset.gradfun_filter );
2928}
2929
2930void Core::toggleGradfun(bool b) {
2931 qDebug("Core::toggleGradfun: %d", b);
2932 if ( b != mset.gradfun_filter) {
2933 mset.gradfun_filter = b;
2934 CHANGE_VF("gradfun", b, pref->filters->item("gradfun").options());
2935 }
2936}
2937
2938void Core::toggleNoise() {
2939 toggleNoise( !mset.noise_filter );
2940}
2941
2942void Core::toggleNoise(bool b) {
2943 qDebug("Core::toggleNoise: %d", b);
2944 if ( b != mset.noise_filter ) {
2945 mset.noise_filter = b;
2946 CHANGE_VF("noise", b, QVariant());
2947 }
2948}
2949
2950void Core::togglePostprocessing() {
2951 togglePostprocessing( !mset.postprocessing_filter );
2952}
2953
2954void Core::togglePostprocessing(bool b) {
2955 qDebug("Core::togglePostprocessing: %d", b);
2956 if ( b != mset.postprocessing_filter ) {
2957 mset.postprocessing_filter = b;
2958 CHANGE_VF("postprocessing", b, QVariant());
2959 }
2960}
2961
2962void Core::changeDenoise(int id) {
2963 qDebug( "Core::changeDenoise: %d", id );
2964 if (id != mset.current_denoiser) {
2965 if (proc->isMPlayer()) {
2966 mset.current_denoiser = id;
2967 restartPlay();
2968 } else {
2969 // MPV
2970 QString dsoft = pref->filters->item("denoise_soft").options();
2971 QString dnormal = pref->filters->item("denoise_normal").options();
2972 // Remove previous filter
2973 switch (mset.current_denoiser) {
2974 case MediaSettings::DenoiseSoft: proc->changeVF("hqdn3d", false, dsoft); break;
2975 case MediaSettings::DenoiseNormal: proc->changeVF("hqdn3d", false, dnormal); break;
2976 }
2977 // New filter
2978 mset.current_denoiser = id;
2979 switch (mset.current_denoiser) {
2980 case MediaSettings::DenoiseSoft: proc->changeVF("hqdn3d", true, dsoft); break;
2981 case MediaSettings::DenoiseNormal: proc->changeVF("hqdn3d", true, dnormal); break;
2982 }
2983 }
2984 }
2985}
2986
2987void Core::changeUnsharp(int id) {
2988 qDebug( "Core::changeUnsharp: %d", id );
2989 if (id != mset.current_unsharp) {
2990 if (proc->isMPlayer()) {
2991 mset.current_unsharp = id;
2992 restartPlay();
2993 } else {
2994 // MPV
2995 // Remove previous filter
2996 switch (mset.current_unsharp) {
2997 // Current is blur
2998 case 1: proc->changeVF("blur", false); break;
2999 // Current if sharpen
3000 case 2: proc->changeVF("sharpen", false); break;
3001 }
3002 // New filter
3003 mset.current_unsharp = id;
3004 switch (mset.current_unsharp) {
3005 case 1: proc->changeVF("blur", true); break;
3006 case 2: proc->changeVF("sharpen", true); break;
3007 }
3008 }
3009 }
3010}
3011
3012void Core::changeUpscale(bool b) {
3013 qDebug( "Core::changeUpscale: %d", b );
3014 if (mset.upscaling_filter != b) {
3015 mset.upscaling_filter = b;
3016 int width = DesktopInfo::desktop_size(mplayerwindow).width();
3017 CHANGE_VF("scale", b, QString::number(width) + ":-2");
3018 }
3019}
3020
3021void Core::changeStereo3d(const QString & in, const QString & out) {
3022 qDebug("Core::changeStereo3d: in: %s out: %s", in.toUtf8().constData(), out.toUtf8().constData());
3023
3024 if ((mset.stereo3d_in != in) || (mset.stereo3d_out != out)) {
3025 if (proc->isMPlayer()) {
3026 mset.stereo3d_in = in;
3027 mset.stereo3d_out = out;
3028 restartPlay();
3029 } else {
3030 // Remove previous filter
3031 if (mset.stereo3d_in != "none" && !mset.stereo3d_out.isEmpty()) {
3032 proc->changeStereo3DFilter(false, mset.stereo3d_in, mset.stereo3d_out);
3033 }
3034
3035 // New filter
3036 mset.stereo3d_in = in;
3037 mset.stereo3d_out = out;
3038 if (mset.stereo3d_in != "none" && !mset.stereo3d_out.isEmpty()) {
3039 proc->changeStereo3DFilter(true, mset.stereo3d_in, mset.stereo3d_out);
3040 }
3041 }
3042 }
3043}
3044
3045void Core::setBrightness(int value) {
3046 qDebug("Core::setBrightness: %d", value);
3047
3048 if (value > 100) value = 100;
3049 if (value < -100) value = -100;
3050
3051 if (value != mset.brightness) {
3052 proc->setPausingPrefix(pausing_prefix());
3053 proc->setBrightness(value);
3054 mset.brightness = value;
3055 displayMessage( tr("Brightness: %1").arg(value) );
3056 emit videoEqualizerNeedsUpdate();
3057 }
3058}
3059
3060
3061void Core::setContrast(int value) {
3062 qDebug("Core::setContrast: %d", value);
3063
3064 if (value > 100) value = 100;
3065 if (value < -100) value = -100;
3066
3067 if (value != mset.contrast) {
3068 proc->setPausingPrefix(pausing_prefix());
3069 proc->setContrast(value);
3070 mset.contrast = value;
3071 displayMessage( tr("Contrast: %1").arg(value) );
3072 emit videoEqualizerNeedsUpdate();
3073 }
3074}
3075
3076void Core::setGamma(int value) {
3077 qDebug("Core::setGamma: %d", value);
3078
3079 if (value > 100) value = 100;
3080 if (value < -100) value = -100;
3081
3082 if (value != mset.gamma) {
3083 proc->setPausingPrefix(pausing_prefix());
3084 proc->setGamma(value);
3085 mset.gamma= value;
3086 displayMessage( tr("Gamma: %1").arg(value) );
3087 emit videoEqualizerNeedsUpdate();
3088 }
3089}
3090
3091void Core::setHue(int value) {
3092 qDebug("Core::setHue: %d", value);
3093
3094 if (value > 100) value = 100;
3095 if (value < -100) value = -100;
3096
3097 if (value != mset.hue) {
3098 proc->setPausingPrefix(pausing_prefix());
3099 proc->setHue(value);
3100 mset.hue = value;
3101 displayMessage( tr("Hue: %1").arg(value) );
3102 emit videoEqualizerNeedsUpdate();
3103 }
3104}
3105
3106void Core::setSaturation(int value) {
3107 qDebug("Core::setSaturation: %d", value);
3108
3109 if (value > 100) value = 100;
3110 if (value < -100) value = -100;
3111
3112 if (value != mset.saturation) {
3113 proc->setPausingPrefix(pausing_prefix());
3114 proc->setSaturation(value);
3115 mset.saturation = value;
3116 displayMessage( tr("Saturation: %1").arg(value) );
3117 emit videoEqualizerNeedsUpdate();
3118 }
3119}
3120
3121void Core::incBrightness() {
3122 setBrightness(mset.brightness + pref->min_step);
3123}
3124
3125void Core::decBrightness() {
3126 setBrightness(mset.brightness - pref->min_step);
3127}
3128
3129void Core::incContrast() {
3130 setContrast(mset.contrast + pref->min_step);
3131}
3132
3133void Core::decContrast() {
3134 setContrast(mset.contrast - pref->min_step);
3135}
3136
3137void Core::incGamma() {
3138 setGamma(mset.gamma + pref->min_step);
3139}
3140
3141void Core::decGamma() {
3142 setGamma(mset.gamma - pref->min_step);
3143}
3144
3145void Core::incHue() {
3146 setHue(mset.hue + pref->min_step);
3147}
3148
3149void Core::decHue() {
3150 setHue(mset.hue - pref->min_step);
3151}
3152
3153void Core::incSaturation() {
3154 setSaturation(mset.saturation + pref->min_step);
3155}
3156
3157void Core::decSaturation() {
3158 setSaturation(mset.saturation - pref->min_step);
3159}
3160
3161void Core::setSpeed( double value ) {
3162 qDebug("Core::setSpeed: %f", value);
3163
3164 if (value < 0.10) value = 0.10;
3165 if (value > 100) value = 100;
3166
3167 mset.speed = value;
3168 proc->setSpeed(value);
3169
3170 displayMessage( tr("Speed: %1").arg(value) );
3171}
3172
3173void Core::incSpeed10() {
3174 qDebug("Core::incSpeed10");
3175 setSpeed( (double) mset.speed + 0.1 );
3176}
3177
3178void Core::decSpeed10() {
3179 qDebug("Core::decSpeed10");
3180 setSpeed( (double) mset.speed - 0.1 );
3181}
3182
3183void Core::incSpeed4() {
3184 qDebug("Core::incSpeed4");
3185 setSpeed( (double) mset.speed + 0.04 );
3186}
3187
3188void Core::decSpeed4() {
3189 qDebug("Core::decSpeed4");
3190 setSpeed( (double) mset.speed - 0.04 );
3191}
3192
3193void Core::incSpeed1() {
3194 qDebug("Core::incSpeed1");
3195 setSpeed( (double) mset.speed + 0.01 );
3196}
3197
3198void Core::decSpeed1() {
3199 qDebug("Core::decSpeed1");
3200 setSpeed( (double) mset.speed - 0.01 );
3201}
3202
3203void Core::doubleSpeed() {
3204 qDebug("Core::doubleSpeed");
3205 setSpeed( (double) mset.speed * 2 );
3206}
3207
3208void Core::halveSpeed() {
3209 qDebug("Core::halveSpeed");
3210 setSpeed( (double) mset.speed / 2 );
3211}
3212
3213void Core::normalSpeed() {
3214 setSpeed(1);
3215}
3216
3217int Core::adjustVolume(int v, int max_vol) {
3218 //qDebug() << "Core::adjustVolume: v:" << v << "max_vol:" << max_vol;
3219 if (max_vol < 100) max_vol = 100;
3220 int vol = v * max_vol / 100;
3221 return vol;
3222}
3223
3224void Core::setVolume(int volume, bool force) {
3225 qDebug("Core::setVolume: %d", volume);
3226
3227 int current_volume = (pref->global_volume ? pref->volume : mset.volume);
3228
3229 if ((volume == current_volume) && (!force)) return;
3230
3231 current_volume = volume;
3232 if (current_volume > 100) current_volume = 100;
3233 if (current_volume < 0) current_volume = 0;
3234
3235 if (proc->isMPV()) {
3236 // MPV
3237 int vol = adjustVolume(current_volume, pref->use_soft_vol ? pref->softvol_max : 100);
3238 proc->setVolume(vol);
3239 } else {
3240 // MPlayer
3241 if (state() == Paused) {
3242 // Change volume later, after quiting pause
3243 change_volume_after_unpause = true;
3244 } else {
3245 proc->setVolume(current_volume);
3246 }
3247 }
3248
3249 if (pref->global_volume) {
3250 pref->volume = current_volume;
3251 pref->mute = false;
3252 } else {
3253 mset.volume = current_volume;
3254 mset.mute = false;
3255 }
3256
3257 updateWidgets();
3258
3259 displayMessage( tr("Volume: %1").arg(current_volume) );
3260 emit volumeChanged( current_volume );
3261}
3262
3263void Core::switchMute() {
3264 qDebug("Core::switchMute");
3265
3266 mset.mute = !mset.mute;
3267 mute(mset.mute);
3268}
3269
3270void Core::mute(bool b) {
3271 qDebug("Core::mute");
3272
3273 proc->setPausingPrefix(pausing_prefix());
3274 proc->mute(b);
3275
3276 if (pref->global_volume) {
3277 pref->mute = b;
3278 } else {
3279 mset.mute = b;
3280 }
3281
3282 updateWidgets();
3283}
3284
3285void Core::incVolume(int step) {
3286 //qDebug("Core::incVolume");
3287 int vol = pref->global_volume ? pref->volume : mset.volume;
3288 setVolume(vol + step);
3289}
3290
3291void Core::decVolume(int step) {
3292 //qDebug("Core::incVolume");
3293 int vol = pref->global_volume ? pref->volume : mset.volume;
3294 setVolume(vol - step);
3295}
3296
3297void Core::incVolume() {
3298 qDebug("Core::incVolume");
3299 incVolume(pref->min_step);
3300}
3301
3302void Core::decVolume() {
3303 qDebug("Core::incVolume");
3304 decVolume(pref->min_step);
3305}
3306
3307void Core::setSubDelay(int delay) {
3308 qDebug("Core::setSubDelay: %d", delay);
3309 mset.sub_delay = delay;
3310 proc->setPausingPrefix(pausing_prefix());
3311 proc->setSubDelay((double) mset.sub_delay/1000);
3312 displayMessage( tr("Subtitle delay: %1 ms").arg(delay) );
3313}
3314
3315void Core::incSubDelay() {
3316 qDebug("Core::incSubDelay");
3317 setSubDelay(mset.sub_delay + 100);
3318}
3319
3320void Core::decSubDelay() {
3321 qDebug("Core::decSubDelay");
3322 setSubDelay(mset.sub_delay - 100);
3323}
3324
3325void Core::setAudioDelay(int delay) {
3326 qDebug("Core::setAudioDelay: %d", delay);
3327 mset.audio_delay = delay;
3328 proc->setPausingPrefix(pausing_prefix());
3329 proc->setAudioDelay((double) mset.audio_delay/1000);
3330 displayMessage( tr("Audio delay: %1 ms").arg(delay) );
3331}
3332
3333void Core::incAudioDelay() {
3334 qDebug("Core::incAudioDelay");
3335 setAudioDelay(mset.audio_delay + 100);
3336}
3337
3338void Core::decAudioDelay() {
3339 qDebug("Core::decAudioDelay");
3340 setAudioDelay(mset.audio_delay - 100);
3341}
3342
3343void Core::incSubPos() {
3344 qDebug("Core::incSubPos");
3345
3346 mset.sub_pos++;
3347 if (mset.sub_pos > 100) mset.sub_pos = 100;
3348 proc->setSubPos(mset.sub_pos);
3349}
3350
3351void Core::decSubPos() {
3352 qDebug("Core::decSubPos");
3353
3354 mset.sub_pos--;
3355 if (mset.sub_pos < 0) mset.sub_pos = 0;
3356 proc->setSubPos(mset.sub_pos);
3357}
3358
3359bool Core::subscale_need_restart() {
3360 bool need_restart = false;
3361
3362 need_restart = (pref->change_sub_scale_should_restart == Preferences::Enabled);
3363 if (pref->change_sub_scale_should_restart == Preferences::Detect) {
3364 if (pref->use_ass_subtitles)
3365 need_restart = (!MplayerVersion::isMplayerAtLeast(25843));
3366 else
3367 need_restart = (!MplayerVersion::isMplayerAtLeast(23745));
3368 }
3369 return need_restart;
3370}
3371
3372void Core::changeSubScale(double value) {
3373 qDebug("Core::changeSubScale: %f", value);
3374
3375 bool need_restart = subscale_need_restart();
3376
3377 if (value < 0) value = 0;
3378
3379 if (pref->use_ass_subtitles) {
3380 if (value != mset.sub_scale_ass) {
3381 mset.sub_scale_ass = value;
3382 if (need_restart) {
3383 restartPlay();
3384 } else {
3385 proc->setSubScale(mset.sub_scale_ass);
3386 }
3387 displayMessage( tr("Font scale: %1").arg(mset.sub_scale_ass) );
3388 }
3389 } else {
3390 // No ass
3391 if (value != mset.sub_scale) {
3392 mset.sub_scale = value;
3393 if (need_restart) {
3394 restartPlay();
3395 } else {
3396 proc->setSubScale(mset.sub_scale);
3397 }
3398 displayMessage( tr("Font scale: %1").arg(mset.sub_scale) );
3399 }
3400 }
3401}
3402
3403void Core::incSubScale() {
3404 double step = 0.20;
3405
3406 if (pref->use_ass_subtitles) {
3407 changeSubScale( mset.sub_scale_ass + step );
3408 } else {
3409 if (subscale_need_restart()) step = 1;
3410 changeSubScale( mset.sub_scale + step );
3411 }
3412}
3413
3414void Core::decSubScale() {
3415 double step = 0.20;
3416
3417 if (pref->use_ass_subtitles) {
3418 changeSubScale( mset.sub_scale_ass - step );
3419 } else {
3420 if (subscale_need_restart()) step = 1;
3421 changeSubScale( mset.sub_scale - step );
3422 }
3423}
3424
3425void Core::changeOSDScale(double value) {
3426 qDebug("Core::changeOSDScale: %f", value);
3427
3428 if (value < 0) value = 0;
3429
3430 if (proc->isMPlayer()) {
3431 if (value != pref->subfont_osd_scale) {
3432 pref->subfont_osd_scale = value;
3433 restartPlay();
3434 }
3435 } else {
3436 if (value != pref->osd_scale) {
3437 pref->osd_scale = value;
3438 proc->setOSDScale(pref->osd_scale);
3439 }
3440 }
3441}
3442
3443void Core::incOSDScale() {
3444 if (proc->isMPlayer()) {
3445 changeOSDScale(pref->subfont_osd_scale + 1);
3446 } else {
3447 changeOSDScale(pref->osd_scale + 0.20);
3448 }
3449}
3450
3451void Core::decOSDScale() {
3452 if (proc->isMPlayer()) {
3453 changeOSDScale(pref->subfont_osd_scale - 1);
3454 } else {
3455 changeOSDScale(pref->osd_scale - 0.20);
3456 }
3457}
3458
3459void Core::incSubStep() {
3460 qDebug("Core::incSubStep");
3461 proc->setSubStep(+1);
3462}
3463
3464void Core::decSubStep() {
3465 qDebug("Core::decSubStep");
3466 proc->setSubStep(-1);
3467}
3468
3469void Core::changeSubVisibility(bool visible) {
3470 qDebug("Core::changeSubVisilibity: %d", visible);
3471 pref->sub_visibility = visible;
3472 proc->setSubtitlesVisibility(pref->sub_visibility);
3473
3474 if (pref->sub_visibility)
3475 displayMessage( tr("Subtitles on") );
3476 else
3477 displayMessage( tr("Subtitles off") );
3478}
3479
3480void Core::changeExternalSubFPS(int fps_id) {
3481 qDebug("Core::setExternalSubFPS: %d", fps_id);
3482 mset.external_subtitles_fps = fps_id;
3483 if (!mset.external_subtitles.isEmpty()) {
3484 restartPlay();
3485 }
3486}
3487
3488// Audio equalizer functions
3489void Core::setAudioEqualizer(AudioEqualizerList values, bool restart) {
3490 if (pref->global_audio_equalizer) {
3491 pref->audio_equalizer = values;
3492 } else {
3493 mset.audio_equalizer = values;
3494 }
3495
3496 if (!restart) {
3497 proc->setAudioEqualizer(Helper::equalizerListToString(values));
3498 } else {
3499 restartPlay();
3500 }
3501
3502 // Infinite recursion
3503 //emit audioEqualizerNeedsUpdate();
3504}
3505
3506void Core::updateAudioEqualizer() {
3507 setAudioEqualizer(pref->global_audio_equalizer ? pref->audio_equalizer : mset.audio_equalizer);
3508}
3509
3510void Core::setAudioEq(int eq, int value) {
3511 if (pref->global_audio_equalizer) {
3512 pref->audio_equalizer[eq] = value;
3513 } else {
3514 mset.audio_equalizer[eq] = value;
3515 }
3516 updateAudioEqualizer();
3517}
3518
3519void Core::setAudioEq0(int value) {
3520 setAudioEq(0, value);
3521}
3522
3523void Core::setAudioEq1(int value) {
3524 setAudioEq(1, value);
3525}
3526
3527void Core::setAudioEq2(int value) {
3528 setAudioEq(2, value);
3529}
3530
3531void Core::setAudioEq3(int value) {
3532 setAudioEq(3, value);
3533}
3534
3535void Core::setAudioEq4(int value) {
3536 setAudioEq(4, value);
3537}
3538
3539void Core::setAudioEq5(int value) {
3540 setAudioEq(5, value);
3541}
3542
3543void Core::setAudioEq6(int value) {
3544 setAudioEq(6, value);
3545}
3546
3547void Core::setAudioEq7(int value) {
3548 setAudioEq(7, value);
3549}
3550
3551void Core::setAudioEq8(int value) {
3552 setAudioEq(8, value);
3553}
3554
3555void Core::setAudioEq9(int value) {
3556 setAudioEq(9, value);
3557}
3558
3559
3560
3561void Core::changeCurrentSec(double sec) {
3562 //qDebug() << "Core::changeCurrentSec:" << sec << "starting_time:" << mset.starting_time;
3563
3564 mset.current_sec = sec;
3565
3566 if (mset.starting_time != -1) {
3567 mset.current_sec -= mset.starting_time;
3568
3569 // handle PTS rollover at MPEG-TS
3570 if (mset.current_sec < 0 && mset.current_demuxer == "mpegts") {
3571 mset.current_sec += 8589934592.0 / 90000.0; // 2^33 / 90 kHz
3572 }
3573 }
3574
3575 if (state() != Playing) {
3576 setState(Playing);
3577 qDebug("Core::changeCurrentSec: mplayer reports that now it's playing");
3578 //emit mediaStartPlay();
3579 //emit stateChanged(state());
3580 }
3581
3582 emit showTime(mset.current_sec);
3583
3584 // Emit posChanged:
3585 static int last_second = 0;
3586
3587 if (floor(sec)==last_second) return; // Update only once per second
3588 last_second = (int) floor(sec);
3589
3590#ifdef SEEKBAR_RESOLUTION
3591 int value = 0;
3592 if ( (mdat.duration > 1) && (mset.current_sec > 1) &&
3593 (mdat.duration > mset.current_sec) )
3594 {
3595 value = ( (int) mset.current_sec * SEEKBAR_RESOLUTION) / (int) mdat.duration;
3596 }
3597 emit positionChanged(value);
3598#else
3599 int perc = 0;
3600 if ( (mdat.duration > 1) && (mset.current_sec > 1) &&
3601 (mdat.duration > mset.current_sec) )
3602 {
3603 perc = ( (int) mset.current_sec * 100) / (int) mdat.duration;
3604 }
3605 emit posChanged( perc );
3606#endif
3607}
3608
3609void Core::gotStartingTime(double time) {
3610 qDebug("Core::gotStartingTime: %f", time);
3611 qDebug("Core::gotStartingTime: current_sec: %f", mset.current_sec);
3612 if ((mset.starting_time == -1.0) && (mset.current_sec == 0)) {
3613 mset.starting_time = time;
3614 qDebug("Core::gotStartingTime: starting time set to %f", time);
3615 }
3616}
3617
3618void Core::gotVideoBitrate(int b) {
3619 mdat.video_bitrate = b;
3620}
3621
3622void Core::gotAudioBitrate(int b) {
3623 mdat.audio_bitrate = b;
3624}
3625
3626void Core::changePause() {
3627 qDebug("Core::changePause");
3628 qDebug("Core::changePause: mplayer reports that it's paused");
3629 setState(Paused);
3630 //emit stateChanged(state());
3631}
3632
3633void Core::changeDeinterlace(int ID) {
3634 qDebug("Core::changeDeinterlace: %d", ID);
3635
3636 if (ID != mset.current_deinterlacer) {
3637 if (proc->isMPlayer()) {
3638 mset.current_deinterlacer = ID;
3639 restartPlay();
3640 } else {
3641 // MPV
3642 // Remove previous filter
3643 switch (mset.current_deinterlacer) {
3644 case MediaSettings::L5: proc->changeVF("l5", false); break;
3645 case MediaSettings::Yadif: proc->changeVF("yadif", false); break;
3646 case MediaSettings::LB: proc->changeVF("lb", false); break;
3647 case MediaSettings::Yadif_1: proc->changeVF("yadif", false, "1"); break;
3648 case MediaSettings::Kerndeint: proc->changeVF("kerndeint", false, "5"); break;
3649 }
3650 mset.current_deinterlacer = ID;
3651 // New filter
3652 switch (mset.current_deinterlacer) {
3653 case MediaSettings::L5: proc->changeVF("l5", true); break;
3654 case MediaSettings::Yadif: proc->changeVF("yadif", true); break;
3655 case MediaSettings::LB: proc->changeVF("lb", true); break;
3656 case MediaSettings::Yadif_1: proc->changeVF("yadif", true, "1"); break;
3657 case MediaSettings::Kerndeint: proc->changeVF("kerndeint", true, "5"); break;
3658 }
3659 }
3660 }
3661}
3662
3663
3664
3665void Core::changeSubtitle(int ID) {
3666 qDebug("Core::changeSubtitle: %d", ID);
3667
3668 mset.current_sub_id = ID;
3669 if (ID==MediaSettings::SubNone) {
3670 ID=-1;
3671 }
3672
3673 if (ID==MediaSettings::NoneSelected) {
3674 ID=-1;
3675 qDebug("Core::changeSubtitle: subtitle is NoneSelected, this shouldn't happen. ID set to -1.");
3676 }
3677
3678 qDebug("Core::changeSubtitle: ID: %d", ID);
3679
3680 int real_id = -1;
3681 if (ID == -1) {
3682 proc->disableSubtitles();
3683 } else {
3684 bool valid_item = ( (ID >= 0) && (ID < mdat.subs.numItems()) );
3685 if (!valid_item) qWarning("Core::changeSubtitle: ID: %d is not valid!", ID);
3686 if ( (mdat.subs.numItems() > 0) && (valid_item) ) {
3687 real_id = mdat.subs.itemAt(ID).ID();
3688 proc->setSubtitle(mdat.subs.itemAt(ID).type(), real_id);
3689 } else {
3690 qWarning("Core::changeSubtitle: subtitle list is empty!");
3691 }
3692 }
3693
3694 updateWidgets();
3695}
3696
3697void Core::nextSubtitle() {
3698 qDebug("Core::nextSubtitle");
3699
3700 if ( (mset.current_sub_id == MediaSettings::SubNone) &&
3701 (mdat.subs.numItems() > 0) )
3702 {
3703 changeSubtitle(0);
3704 }
3705 else {
3706 int item = mset.current_sub_id + 1;
3707 if (item >= mdat.subs.numItems()) {
3708 item = MediaSettings::SubNone;
3709 }
3710 changeSubtitle( item );
3711 }
3712}
3713
3714#ifdef MPV_SUPPORT
3715void Core::changeSecondarySubtitle(int ID) {
3716 // MPV only
3717 qDebug("Core::changeSecondarySubtitle: %d", ID);
3718
3719 mset.current_secondary_sub_id = ID;
3720 if (ID == MediaSettings::SubNone) {
3721 ID = -1;
3722 }
3723 if (ID == MediaSettings::NoneSelected) {
3724 ID = -1;
3725 }
3726
3727 if (ID == -1) {
3728 proc->disableSecondarySubtitles();
3729 } else {
3730 int real_id = -1;
3731 bool valid_item = ( (ID >= 0) && (ID < mdat.subs.numItems()) );
3732 if (!valid_item) qWarning("Core::changeSecondarySubtitle: ID: %d is not valid!", ID);
3733 if ( (mdat.subs.numItems() > 0) && (valid_item) ) {
3734 real_id = mdat.subs.itemAt(ID).ID();
3735 proc->setSecondarySubtitle(real_id);
3736 }
3737 }
3738}
3739#endif
3740
3741void Core::changeAudio(int ID, bool allow_restart) {
3742 qDebug("Core::changeAudio: ID: %d, allow_restart: %d", ID, allow_restart);
3743
3744 if (ID!=mset.current_audio_id) {
3745 mset.current_audio_id = ID;
3746 qDebug("changeAudio: ID: %d", ID);
3747
3748 bool need_restart = false;
3749 #ifdef OBSOLETE_FAST_AUDIO_CHANGE
3750 if (allow_restart) {
3751 need_restart = (pref->fast_audio_change == Preferences::Disabled);
3752 if (pref->fast_audio_change == Preferences::Detect) {
3753 need_restart = (!MplayerVersion::isMplayerAtLeast(21441));
3754 }
3755 }
3756 #endif
3757
3758 if (need_restart) {
3759 restartPlay();
3760 } else {
3761 proc->setAudio(ID);
3762 // Workaround for a mplayer problem in windows,
3763 // volume is too loud after changing audio.
3764
3765 // Workaround too for a mplayer problem in linux,
3766 // the volume is reduced if using -softvol-max.
3767
3768 if (proc->isMPlayer()) {
3769 if (pref->mplayer_additional_options.contains("-volume")) {
3770 qDebug("Core::changeAudio: don't set volume since -volume is used");
3771 } else {
3772 if (pref->global_volume) {
3773 setVolume( pref->volume, true);
3774 if (pref->mute) mute(true);
3775 } else {
3776 setVolume( mset.volume, true );
3777 if (mset.mute) mute(true); // if muted, mute again
3778 }
3779 }
3780 }
3781 updateWidgets();
3782 }
3783 }
3784}
3785
3786void Core::nextAudio() {
3787 qDebug("Core::nextAudio");
3788
3789 int item = mdat.audios.find( mset.current_audio_id );
3790 if (item == -1) {
3791 qWarning("Core::nextAudio: audio ID %d not found!", mset.current_audio_id);
3792 } else {
3793 qDebug( "Core::nextAudio: numItems: %d, item: %d", mdat.audios.numItems(), item);
3794 item++;
3795 if (item >= mdat.audios.numItems()) item=0;
3796 int ID = mdat.audios.itemAt(item).ID();
3797 qDebug( "Core::nextAudio: item: %d, ID: %d", item, ID);
3798 changeAudio( ID );
3799 }
3800}
3801
3802void Core::changeVideo(int ID, bool allow_restart) {
3803 qDebug("Core::changeVideo: ID: %d, allow_restart: %d", ID, allow_restart);
3804
3805 if (ID != mset.current_video_id) {
3806 mset.current_video_id = ID;
3807 qDebug("Core::changeVideo: ID set to: %d", ID);
3808
3809 bool need_restart = false;
3810 if (allow_restart) {
3811 // afaik lavf doesn't require to restart, any other?
3812 need_restart = ((mdat.demuxer != "lavf") && (mdat.demuxer != "mpegts"));
3813 }
3814
3815 if (need_restart) {
3816 restartPlay();
3817 } else {
3818 if (mdat.demuxer == "nsv") {
3819 // Workaround a problem with the nsv demuxer
3820 qWarning("Core::changeVideo: not changing the video with nsv to prevent mplayer go crazy");
3821 } else {
3822 proc->setVideo(ID);
3823 }
3824 }
3825 }
3826}
3827
3828void Core::nextVideo() {
3829 qDebug("Core::nextVideo");
3830
3831 int item = mdat.videos.find( mset.current_video_id );
3832 if (item == -1) {
3833 qWarning("Core::nextVideo: video ID %d not found!", mset.current_video_id);
3834 } else {
3835 qDebug( "Core::nextVideo: numItems: %d, item: %d", mdat.videos.numItems(), item);
3836 item++;
3837 if (item >= mdat.videos.numItems()) item=0;
3838 int ID = mdat.videos.itemAt(item).ID();
3839 qDebug( "Core::nextVideo: item: %d, ID: %d", item, ID);
3840 changeVideo( ID );
3841 }
3842}
3843
3844#if PROGRAM_SWITCH
3845void Core::changeProgram(int ID) {
3846 qDebug("Core::changeProgram: %d", ID);
3847
3848 if (ID != mset.current_program_id) {
3849 mset.current_program_id = ID;
3850 proc->setTSProgram(ID);
3851
3852 /*
3853 mset.current_video_id = MediaSettings::NoneSelected;
3854 mset.current_audio_id = MediaSettings::NoneSelected;
3855
3856 updateWidgets();
3857 */
3858 }
3859}
3860
3861void Core::nextProgram() {
3862 qDebug("Core::nextProgram");
3863 // Not implemented yet
3864}
3865
3866#endif
3867
3868void Core::changeTitle(int ID) {
3869 if (mdat.type == TYPE_VCD) {
3870 // VCD
3871 openVCD( ID );
3872 }
3873 else
3874 if (mdat.type == TYPE_AUDIO_CD) {
3875 // AUDIO CD
3876 openAudioCD( ID );
3877 }
3878 else
3879 if (mdat.type == TYPE_DVD) {
3880 #if DVDNAV_SUPPORT
3881 if (mdat.filename.startsWith("dvdnav:")) {
3882 proc->setTitle(ID);
3883 } else {
3884 #endif
3885 DiscData disc_data = DiscName::split(mdat.filename);
3886 disc_data.title = ID;
3887 QString dvd_url = DiscName::join(disc_data);
3888
3889 openDVD( DiscName::join(disc_data) );
3890 #if DVDNAV_SUPPORT
3891 }
3892 #endif
3893 }
3894#ifdef BLURAY_SUPPORT
3895 else
3896 if (mdat.type == TYPE_BLURAY) {
3897 //DiscName::test();
3898
3899 DiscData disc_data = DiscName::split(mdat.filename);
3900 disc_data.title = ID;
3901 QString bluray_url = DiscName::join(disc_data);
3902 qDebug("Core::changeTitle: bluray_url: %s", bluray_url.toUtf8().constData());
3903 openBluRay(bluray_url);
3904 }
3905#endif
3906}
3907
3908void Core::changeChapter(int ID) {
3909 qDebug("Core::changeChapter: ID: %d", ID);
3910 proc->setChapter(ID);
3911}
3912
3913int Core::firstChapter() {
3914 if ( (MplayerVersion::isMplayerAtLeast(25391)) &&
3915 (!MplayerVersion::isMplayerAtLeast(29407)) )
3916 return 1;
3917 else
3918 return 0;
3919}
3920
3921int Core::firstDVDTitle() {
3922 if (proc->isMPV()) {
3923 return 0;
3924 } else {
3925 return 1;
3926 }
3927}
3928
3929int Core::firstBlurayTitle() {
3930 if (proc->isMPV()) {
3931 return 0;
3932 } else {
3933 return 1;
3934 }
3935}
3936
3937void Core::prevChapter() {
3938 qDebug("Core::prevChapter");
3939 proc->previousChapter();
3940}
3941
3942void Core::nextChapter() {
3943 qDebug("Core::nextChapter");
3944 proc->nextChapter();
3945}
3946
3947void Core::changeAngle(int ID) {
3948 qDebug("Core::changeAngle: ID: %d", ID);
3949
3950 if (ID != mset.current_angle_id) {
3951 mset.current_angle_id = ID;
3952 restartPlay();
3953 }
3954}
3955
3956void Core::changeAspectRatio( int ID ) {
3957 qDebug("Core::changeAspectRatio: %d", ID);
3958
3959 mset.aspect_ratio_id = ID;
3960
3961 double asp = mset.aspectToNum( (MediaSettings::Aspect) ID);
3962
3963 if (!pref->use_mplayer_window) {
3964 mplayerwindow->setAspect(asp);
3965 } else {
3966 // Using mplayer own window
3967 if (!mdat.novideo) {
3968 if (ID == MediaSettings::AspectAuto) {
3969 asp = mdat.video_aspect;
3970 }
3971 proc->setAspect(asp);
3972 }
3973 }
3974
3975 QString asp_name = MediaSettings::aspectToString( (MediaSettings::Aspect) mset.aspect_ratio_id);
3976 displayMessage( tr("Aspect ratio: %1").arg(asp_name) );
3977}
3978
3979void Core::nextAspectRatio() {
3980 // Ordered list
3981 QList<int> s;
3982 s << MediaSettings::AspectNone
3983 << MediaSettings::AspectAuto
3984 << MediaSettings::Aspect11 // 1
3985 << MediaSettings::Aspect54 // 1.25
3986 << MediaSettings::Aspect43 // 1.33
3987 << MediaSettings::Aspect118 // 1.37
3988 << MediaSettings::Aspect1410 // 1.4
3989 << MediaSettings::Aspect32 // 1.5
3990 << MediaSettings::Aspect149 // 1.55
3991 << MediaSettings::Aspect1610 // 1.6
3992 << MediaSettings::Aspect169 // 1.77
3993 << MediaSettings::Aspect235; // 2.35
3994
3995 int i = s.indexOf( mset.aspect_ratio_id ) + 1;
3996 if (i >= s.count()) i = 0;
3997
3998 int new_aspect_id = s[i];
3999
4000 changeAspectRatio( new_aspect_id );
4001 updateWidgets();
4002}
4003
4004void Core::nextWheelFunction() {
4005 int a = pref->wheel_function;
4006
4007 bool done = false;
4008 if(((int ) pref->wheel_function_cycle)==0)
4009 return;
4010 while(!done){
4011 // get next a
4012
4013 a = a*2;
4014 if(a==32)
4015 a = 2;
4016 // See if we are done
4017 if (pref->wheel_function_cycle.testFlag((Preferences::WheelFunction)a))
4018 done = true;
4019 }
4020 pref->wheel_function = a;
4021 QString m = "";
4022 switch(a){
4023 case Preferences::Seeking:
4024 m = tr("Mouse wheel seeks now");
4025 break;
4026 case Preferences::Volume:
4027 m = tr("Mouse wheel changes volume now");
4028 break;
4029 case Preferences::Zoom:
4030 m = tr("Mouse wheel changes zoom level now");
4031 break;
4032 case Preferences::ChangeSpeed:
4033 m = tr("Mouse wheel changes speed now");
4034 break;
4035 }
4036 displayMessage(m);
4037}
4038
4039void Core::changeLetterbox(bool b) {
4040 qDebug("Core::changeLetterbox: %d", b);
4041
4042 if (mset.add_letterbox != b) {
4043 mset.add_letterbox = b;
4044 CHANGE_VF("letterbox", b, DesktopInfo::desktop_aspectRatio(mplayerwindow));
4045 }
4046}
4047
4048void Core::changeLetterboxOnFullscreen(bool b) {
4049 qDebug("Core::changeLetterboxOnFullscreen: %d", b);
4050 CHANGE_VF("letterbox", b, DesktopInfo::desktop_aspectRatio(mplayerwindow));
4051}
4052
4053void Core::changeOSD(int v) {
4054 qDebug("Core::changeOSD: %d", v);
4055
4056 pref->osd = v;
4057
4058 proc->setPausingPrefix(pausing_prefix());
4059 proc->setOSD(pref->osd);
4060
4061 updateWidgets();
4062}
4063
4064void Core::nextOSD() {
4065 int osd = pref->osd + 1;
4066 if (osd > Preferences::SeekTimerTotal) {
4067 osd = Preferences::None;
4068 }
4069 changeOSD( osd );
4070}
4071
4072void Core::changeRotate(int r) {
4073 qDebug("Core::changeRotate: %d", r);
4074
4075 if (mset.rotate != r) {
4076 if (proc->isMPlayer()) {
4077 mset.rotate = r;
4078 restartPlay();
4079 } else {
4080 // MPV
4081 // Remove previous filter
4082 switch (mset.rotate) {
4083 case MediaSettings::Clockwise_flip: proc->changeVF("rotate", false, MediaSettings::Clockwise_flip); break;
4084 case MediaSettings::Clockwise: proc->changeVF("rotate", false, MediaSettings::Clockwise); break;
4085 case MediaSettings::Counterclockwise: proc->changeVF("rotate", false, MediaSettings::Counterclockwise); break;
4086 case MediaSettings::Counterclockwise_flip: proc->changeVF("rotate", false, MediaSettings::Counterclockwise_flip); break;
4087 }
4088 mset.rotate = r;
4089 // New filter
4090 switch (mset.rotate) {
4091 case MediaSettings::Clockwise_flip: proc->changeVF("rotate", true, MediaSettings::Clockwise_flip); break;
4092 case MediaSettings::Clockwise: proc->changeVF("rotate", true, MediaSettings::Clockwise); break;
4093 case MediaSettings::Counterclockwise: proc->changeVF("rotate", true, MediaSettings::Counterclockwise); break;
4094 case MediaSettings::Counterclockwise_flip: proc->changeVF("rotate", true, MediaSettings::Counterclockwise_flip); break;
4095 }
4096 }
4097 }
4098}
4099
4100#if USE_ADAPTER
4101void Core::changeAdapter(int n) {
4102 qDebug("Core::changeScreen: %d", n);
4103
4104 if (pref->adapter != n) {
4105 pref->adapter = n;
4106 restartPlay();
4107 }
4108}
4109#endif
4110
4111#if 0
4112void Core::changeSize(int n) {
4113 if ( /*(n != pref->size_factor) &&*/ (!pref->use_mplayer_window) ) {
4114 pref->size_factor = n;
4115
4116 emit needResize(mset.win_width, mset.win_height);
4117 updateWidgets();
4118 }
4119}
4120
4121void Core::toggleDoubleSize() {
4122 if (pref->size_factor != 100)
4123 changeSize(100);
4124 else
4125 changeSize(200);
4126}
4127#endif
4128
4129void Core::changeZoom(double p) {
4130 qDebug("Core::changeZoom: %f", p);
4131 if (p < ZOOM_MIN) p = ZOOM_MIN;
4132
4133 mset.zoom_factor = p;
4134 mplayerwindow->setZoom(p);
4135 displayMessage( tr("Zoom: %1").arg(mset.zoom_factor) );
4136}
4137
4138void Core::resetZoom() {
4139 changeZoom(1.0);
4140}
4141
4142void Core::autoZoom() {
4143 double video_aspect = mset.aspectToNum( (MediaSettings::Aspect) mset.aspect_ratio_id);
4144
4145 if (video_aspect <= 0) {
4146 QSize w = mplayerwindow->videoLayer()->size();
4147 video_aspect = (double) w.width() / w.height();
4148 }
4149
4150 double screen_aspect = DesktopInfo::desktop_aspectRatio(mplayerwindow);
4151 double zoom_factor;
4152
4153 if (video_aspect > screen_aspect)
4154 zoom_factor = video_aspect / screen_aspect;
4155 else
4156 zoom_factor = screen_aspect / video_aspect;
4157
4158 qDebug("Core::autoZoom: video_aspect: %f", video_aspect);
4159 qDebug("Core::autoZoom: screen_aspect: %f", screen_aspect);
4160 qDebug("Core::autoZoom: zoom_factor: %f", zoom_factor);
4161
4162 changeZoom(zoom_factor);
4163}
4164
4165void Core::autoZoomFromLetterbox(double aspect) {
4166 qDebug("Core::autoZoomFromLetterbox: %f", aspect);
4167
4168 // Probably there's a much easy way to do this, but I'm not good with maths...
4169
4170 QSize desktop = DesktopInfo::desktop_size(mplayerwindow);
4171
4172 double video_aspect = mset.aspectToNum( (MediaSettings::Aspect) mset.aspect_ratio_id);
4173
4174 if (video_aspect <= 0) {
4175 QSize w = mplayerwindow->videoLayer()->size();
4176 video_aspect = (double) w.width() / w.height();
4177 }
4178
4179 // Calculate size of the video in fullscreen
4180 QSize video;
4181 video.setHeight( desktop.height() );;
4182 video.setWidth( (int) (video.height() * video_aspect) );
4183 if (video.width() > desktop.width()) {
4184 video.setWidth( desktop.width() );;
4185 video.setHeight( (int) (video.width() / video_aspect) );
4186 }
4187
4188 qDebug("Core::autoZoomFromLetterbox: max. size of video: %d %d", video.width(), video.height());
4189
4190 // Calculate the size of the actual video inside the letterbox
4191 QSize actual_video;
4192 actual_video.setWidth( video.width() );
4193 actual_video.setHeight( (int) (actual_video.width() / aspect) );
4194
4195 qDebug("Core::autoZoomFromLetterbox: calculated size of actual video for aspect %f: %d %d", aspect, actual_video.width(), actual_video.height());
4196
4197 double zoom_factor = (double) desktop.height() / actual_video.height();
4198
4199 qDebug("Core::autoZoomFromLetterbox: calculated zoom factor: %f", zoom_factor);
4200 changeZoom(zoom_factor);
4201}
4202
4203void Core::autoZoomFor169() {
4204 autoZoomFromLetterbox((double) 16 / 9);
4205}
4206
4207void Core::autoZoomFor235() {
4208 autoZoomFromLetterbox(2.35);
4209}
4210
4211void Core::incZoom() {
4212 qDebug("Core::incZoom");
4213 changeZoom( mset.zoom_factor + ZOOM_STEP );
4214}
4215
4216void Core::decZoom() {
4217 qDebug("Core::decZoom");
4218 changeZoom( mset.zoom_factor - ZOOM_STEP );
4219}
4220
4221void Core::showFilenameOnOSD() {
4222 proc->showFilenameOnOSD();
4223}
4224
4225void Core::showTimeOnOSD() {
4226 proc->showTimeOnOSD();
4227}
4228
4229void Core::toggleDeinterlace() {
4230 qDebug("Core::toggleDeinterlace");
4231 proc->toggleDeinterlace();
4232}
4233
4234void Core::changeUseCustomSubStyle(bool b) {
4235 qDebug("Core::changeUseCustomSubStyle: %d", b);
4236
4237 if (pref->enable_ass_styles != b) {
4238 pref->enable_ass_styles = b;
4239 if (proc->isRunning()) restartPlay();
4240 }
4241}
4242
4243void Core::toggleForcedSubsOnly(bool b) {
4244 qDebug("Core::toggleForcedSubsOnly: %d", b);
4245
4246 if (pref->use_forced_subs_only != b) {
4247 pref->use_forced_subs_only = b;
4248 //if (proc->isRunning()) restartPlay();
4249 proc->setSubForcedOnly(b);
4250 }
4251}
4252
4253void Core::changeClosedCaptionChannel(int c) {
4254 qDebug("Core::changeClosedCaptionChannel: %d", c);
4255 if (c != mset.closed_caption_channel) {
4256 mset.closed_caption_channel = c;
4257 if (proc->isRunning()) restartPlay();
4258 }
4259}
4260
4261/*
4262void Core::nextClosedCaptionChannel() {
4263 int c = mset.closed_caption_channel;
4264 c++;
4265 if (c > 4) c = 0;
4266 changeClosedCaptionChannel(c);
4267}
4268
4269void Core::prevClosedCaptionChannel() {
4270 int c = mset.closed_caption_channel;
4271 c--;
4272 if (c < 0) c = 4;
4273 changeClosedCaptionChannel(c);
4274}
4275*/
4276
4277#if DVDNAV_SUPPORT
4278// dvdnav buttons
4279void Core::dvdnavUp() {
4280 qDebug("Core::dvdnavUp");
4281 proc->discButtonPressed("up");
4282}
4283
4284void Core::dvdnavDown() {
4285 qDebug("Core::dvdnavDown");
4286 proc->discButtonPressed("down");
4287}
4288
4289void Core::dvdnavLeft() {
4290 qDebug("Core::dvdnavLeft");
4291 proc->discButtonPressed("left");
4292}
4293
4294void Core::dvdnavRight() {
4295 qDebug("Core::dvdnavRight");
4296 proc->discButtonPressed("right");
4297}
4298
4299void Core::dvdnavMenu() {
4300 qDebug("Core::dvdnavMenu");
4301 proc->discButtonPressed("menu");
4302}
4303
4304void Core::dvdnavSelect() {
4305 qDebug("Core::dvdnavSelect");
4306 proc->discButtonPressed("select");
4307}
4308
4309void Core::dvdnavPrev() {
4310 qDebug("Core::dvdnavPrev");
4311 proc->discButtonPressed("prev");
4312}
4313
4314void Core::dvdnavMouse() {
4315 qDebug("Core::dvdnavMouse");
4316
4317 if ((state() == Playing) && (mdat.filename.startsWith("dvdnav:"))) {
4318 proc->discButtonPressed("mouse");
4319 }
4320}
4321#endif
4322
4323void Core::displayMessage(QString text) {
4324 qDebug("Core::displayMessage");
4325 emit showMessage(text);
4326
4327 if ((pref->fullscreen) && (state() != Paused)) {
4328 displayTextOnOSD( text );
4329 }
4330}
4331
4332void Core::displayScreenshotName(QString filename) {
4333 qDebug("Core::displayScreenshotName: %s", filename.toUtf8().constData());
4334
4335 QFileInfo fi(filename);
4336
4337 QString text = tr("Screenshot saved as %1").arg(fi.fileName());
4338 //QString text = QString("Screenshot saved as %1").arg(fi.fileName());
4339
4340#ifdef MPLAYER2_SUPPORT
4341 if (MplayerVersion::isMplayer2()) {
4342 displayTextOnOSD(text, 3000, 1, "");
4343 }
4344 else
4345#endif
4346 if (MplayerVersion::isMplayerAtLeast(27665)) {
4347 displayTextOnOSD(text, 3000, 1, "pausing_keep_force");
4348 }
4349 else
4350 if (state() != Paused) {
4351 // Dont' show the message on OSD while in pause, otherwise
4352 // the video goes forward a frame.
4353 displayTextOnOSD(text, 3000, 1, "pausing_keep");
4354 }
4355
4356 emit showMessage(text);
4357}
4358
4359void Core::displayUpdatingFontCache() {
4360 qDebug("Core::displayUpdatingFontCache");
4361 emit showMessage( tr("Updating the font cache. This may take some seconds...") );
4362}
4363
4364void Core::displayBuffering() {
4365 setState(Buffering);
4366// emit showMessage(tr("Buffering..."));
4367}
4368
4369void Core::displayPlaying() {
4370 qDebug("Core::displayPlaying");
4371 setState(Buffering);
4372 emit showMessage(tr("Starting..."), 60000);
4373}
4374
4375void Core::gotWindowResolution(int w, int h) {
4376 qDebug("Core::gotWindowResolution: %d, %d", w, h);
4377 //double aspect = (double) w/h;
4378
4379 if (pref->use_mplayer_window) {
4380 emit noVideo();
4381 } else {
4382 if ((pref->resize_method==Preferences::Afterload) && (we_are_restarting)) {
4383 // Do nothing
4384 } else {
4385 emit needResize(w,h);
4386 }
4387 }
4388
4389 mset.win_width = w;
4390 mset.win_height = h;
4391
4392 //Override aspect ratio, is this ok?
4393 //mdat.video_aspect = mset.win_aspect();
4394
4395 mplayerwindow->setResolution( w, h );
4396 mplayerwindow->setAspect( mset.win_aspect() );
4397}
4398
4399void Core::gotNoVideo() {
4400 // File has no video (a sound file)
4401
4402 // Reduce size of window
4403 /*
4404 mset.win_width = mplayerwindow->size().width();
4405 mset.win_height = 0;
4406 mplayerwindow->setResolution( mset.win_width, mset.win_height );
4407 emit needResize( mset.win_width, mset.win_height );
4408 */
4409 //mplayerwindow->showLogo(true);
4410 emit noVideo();
4411}
4412
4413void Core::gotVO(QString vo) {
4414 qDebug() << "Core::gotVO:" << vo;
4415
4416 /*
4417 if (pref->vo.isEmpty()) {
4418 qDebug("Core::gotVO: saving vo");
4419 pref->vo = vo;
4420 }
4421 */
4422}
4423
4424void Core::gotAO(QString ao) {
4425 qDebug() << "Core::gotAO:" << ao;
4426
4427 /*
4428 if (pref->ao.isEmpty()) {
4429 qDebug("Core::gotAO: saving ao");
4430 pref->ao = ao;
4431 }
4432 */
4433}
4434
4435void Core::streamTitleChanged(QString title) {
4436 mdat.stream_title = title;
4437 emit mediaInfoChanged();
4438}
4439
4440void Core::streamTitleAndUrlChanged(QString title, QString url) {
4441 mdat.stream_title = title;
4442 mdat.stream_url = url;
4443 emit mediaInfoChanged();
4444}
4445
4446void Core::sendMediaInfo() {
4447 qDebug("Core::sendMediaInfo");
4448 emit mediaPlaying(mdat.filename, mdat.displayName(pref->show_tag_in_window_title));
4449}
4450
4451//! Called when the state changes
4452void Core::watchState(Core::State state) {
4453#ifdef SCREENSAVER_OFF
4454 #if 0
4455 qDebug("Core::watchState: %d", state);
4456 //qDebug("Core::watchState: has video: %d", !mdat.novideo);
4457
4458 if ((state == Playing) /* && (!mdat.novideo) */) {
4459 disableScreensaver();
4460 } else {
4461 enableScreensaver();
4462 }
4463 #endif
4464#endif
4465
4466 if ((proc->isMPlayer()) && (state == Playing) && (change_volume_after_unpause)) {
4467 // Delayed volume change
4468 qDebug("Core::watchState: delayed volume change");
4469 int volume = (pref->global_volume ? pref->volume : mset.volume);
4470 proc->setVolume(volume);
4471 change_volume_after_unpause = false;
4472 }
4473}
4474
4475void Core::checkIfVideoIsHD() {
4476 qDebug("Core::checkIfVideoIsHD");
4477
4478 // Check if the video is in HD and uses ffh264 codec.
4479 if ((mdat.video_codec=="ffh264") && (mset.win_height >= pref->HD_height)) {
4480 qDebug("Core::checkIfVideoIsHD: video == ffh264 and height >= %d", pref->HD_height);
4481 if (!mset.is264andHD) {
4482 mset.is264andHD = true;
4483 if (pref->h264_skip_loop_filter == Preferences::LoopDisabledOnHD) {
4484 qDebug("Core::checkIfVideoIsHD: we're about to restart the video");
4485 restartPlay();
4486 }
4487 }
4488 } else {
4489 mset.is264andHD = false;
4490 // FIXME: if the video was previously marked as HD, and now it's not
4491 // then the video should restart too.
4492 }
4493}
4494
4495#if DELAYED_AUDIO_SETUP_ON_STARTUP && NOTIFY_AUDIO_CHANGES
4496#error "DELAYED_AUDIO_SETUP_ON_STARTUP and NOTIFY_AUDIO_CHANGES can't be both defined"
4497#endif
4498
4499#if DELAYED_AUDIO_SETUP_ON_STARTUP
4500void Core::initAudioTrack() {
4501 qDebug("Core::initAudioTrack");
4502
4503 // First audio if none selected
4504 if ( (mset.current_audio_id == MediaSettings::NoneSelected) &&
4505 (mdat.audios.numItems() > 0) )
4506 {
4507 // Don't set mset.current_audio_id here! changeAudio will do.
4508 // Otherwise changeAudio will do nothing.
4509
4510 int audio = mdat.audios.itemAt(0).ID(); // First one
4511 if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) {
4512 audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID();
4513 }
4514
4515 // Check if one of the audio tracks is the user preferred.
4516 if (!pref->audio_lang.isEmpty()) {
4517 int res = mdat.audios.findLang( pref->audio_lang );
4518 if (res != -1) audio = res;
4519 }
4520
4521 changeAudio( audio );
4522 }
4523}
4524#endif
4525
4526#if NOTIFY_VIDEO_CHANGES
4527void Core::initVideoTrack(const Tracks & videos) {
4528 qDebug("Core::initVideoTrack");
4529 mdat.videos = videos;
4530 initializeMenus();
4531 updateWidgets();
4532}
4533#endif
4534
4535#if NOTIFY_AUDIO_CHANGES
4536void Core::initAudioTrack(const Tracks & audios) {
4537 qDebug("Core::initAudioTrack");
4538
4539 qDebug("Core::initAudioTrack: num_items: %d", mdat.audios.numItems());
4540
4541 bool restore_audio = ((mdat.audios.numItems() > 0) ||
4542 (mset.current_audio_id != MediaSettings::NoneSelected));
4543
4544 mdat.audios = audios;
4545
4546 qDebug("Core::initAudioTrack: list of audios:");
4547 mdat.audios.list();
4548
4549 initializeMenus();
4550
4551 if (!restore_audio) {
4552 // Select initial track
4553 qDebug("Core::initAudioTrack: selecting initial track");
4554
4555 int audio = mdat.audios.itemAt(0).ID(); // First one
4556 if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) {
4557 audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID();
4558 }
4559
4560 // Check if one of the audio tracks is the user preferred.
4561 if (!pref->audio_lang.isEmpty()) {
4562 int res = mdat.audios.findLang( pref->audio_lang );
4563 if (res != -1) audio = res;
4564 }
4565
4566 changeAudio( audio );
4567 } else {
4568 // Try to restore previous audio track
4569 qDebug("Core::initAudioTrack: restoring audio");
4570 // Nothing to do, the audio is already set with -aid
4571 }
4572
4573 updateWidgets();
4574
4575 emit audioTracksChanged();
4576}
4577#endif
4578
4579#if NOTIFY_SUB_CHANGES
4580void Core::initSubtitleTrack(const SubTracks & subs) {
4581 qDebug("Core::initSubtitleTrack");
4582
4583 qDebug("Core::initSubtitleTrack: num_items: %d", mdat.subs.numItems());
4584
4585 bool restore_subs = ((mdat.subs.numItems() > 0) ||
4586 (mset.current_sub_id != MediaSettings::NoneSelected));
4587
4588 // Save current sub
4589 SubData::Type previous_sub_type = SubData::Sub;
4590 int previous_sub_id = -1;
4591 if (mdat.subs.numItems() > 0) {
4592 if ((mset.current_sub_id != MediaSettings::SubNone) &&
4593 (mset.current_sub_id != MediaSettings::NoneSelected))
4594 {
4595 previous_sub_type = mdat.subs.itemAt(mset.current_sub_id).type();
4596 previous_sub_id = mdat.subs.itemAt(mset.current_sub_id).ID();
4597 }
4598 }
4599 qDebug("Core::initSubtitleTrack: previous subtitle: type: %d id: %d", previous_sub_type, previous_sub_id);
4600
4601 mdat.subs = subs;
4602
4603 qDebug("Core::initSubtitleTrack: list of subtitles:");
4604 mdat.subs.list();
4605
4606 initializeMenus();
4607
4608 if (just_unloaded_external_subs) {
4609 qDebug("Core::initSubtitleTrack: just_unloaded_external_subs: true");
4610 restore_subs = false;
4611 just_unloaded_external_subs = false;
4612 }
4613 if (just_loaded_external_subs) {
4614 qDebug("Core::initSubtitleTrack: just_loaded_external_subs: true");
4615 restore_subs = false;
4616 just_loaded_external_subs = false;
4617
4618 QFileInfo fi(mset.external_subtitles);
4619 bool is_idx = (fi.suffix().toLower() == "idx");
4620 if (proc->isMPV()) is_idx = false; // Hack to ignore the idx extension with mpv
4621
4622 if (!is_idx) {
4623 // The loaded subtitle file is the last one, so
4624 // try to select that one.
4625 if (mdat.subs.numItems() > 0) {
4626 int selected_subtitle = mdat.subs.numItems()-1; // If everything fails, use the last one
4627
4628 // Try to find the subtitle file in the list
4629 for (int n = 0; n < mdat.subs.numItems(); n++) {
4630 SubData sub = mdat.subs.itemAt(n);
4631 if ((sub.type() == SubData::File) && (sub.filename() == mset.external_subtitles)) {
4632 selected_subtitle = n;
4633 qDebug("Core::initSubtitleTrack: external subtitle found: #%d", n);
4634 break;
4635 }
4636 }
4637 changeSubtitle( selected_subtitle );
4638 goto end;
4639 }
4640 }
4641 }
4642
4643 if (!restore_subs) {
4644 // Select initial track
4645 qDebug("Core::initSubtitleTrack: selecting initial track");
4646
4647 if (!pref->autoload_sub) {
4648 changeSubtitle( MediaSettings::SubNone );
4649 } else {
4650 //Select first subtitle
4651 int sub = mdat.subs.selectOne( pref->subtitle_lang, pref->initial_subtitle_track-1 );
4652 changeSubtitle( sub );
4653 }
4654 } else {
4655 // Try to restore previous subtitle track
4656 qDebug("Core::initSubtitleTrack: restoring subtitle");
4657
4658 if (mset.current_sub_id == MediaSettings::SubNone) {
4659 changeSubtitle( MediaSettings::SubNone );
4660 }
4661 else
4662 if (mset.current_sub_id != MediaSettings::NoneSelected) {
4663 // Try to find old subtitle
4664 int item = mset.current_sub_id;
4665 if (previous_sub_id != -1) {
4666 int sub_item = mdat.subs.find(previous_sub_type, previous_sub_id);
4667 if (sub_item > -1) {
4668 item = sub_item;
4669 qDebug("Core::initSubtitleTrack: previous subtitle found: %d", sub_item);
4670 }
4671 }
4672 if (item > -1) {
4673 changeSubtitle(item );
4674 } else {
4675 qDebug("Core::initSubtitleTrack: previous subtitle not found!");
4676 }
4677 }
4678 }
4679end:
4680
4681#ifdef MPV_SUPPORT
4682 changeSecondarySubtitle(mset.current_secondary_sub_id);
4683#endif
4684 updateWidgets();
4685}
4686
4687void Core::setSubtitleTrackAgain(const SubTracks &) {
4688 qDebug("Core::setSubtitleTrackAgain");
4689 changeSubtitle( mset.current_sub_id );
4690}
4691#endif
4692
4693#if NOTIFY_CHAPTER_CHANGES
4694void Core::updateChapterInfo(const Chapters & chapters) {
4695 qDebug("Core::updateChapterInfo");
4696 mdat.chapters = chapters;
4697 initializeMenus();
4698 updateWidgets();
4699}
4700#endif
4701
4702#if DVDNAV_SUPPORT
4703void Core::dvdTitleChanged(int title) {
4704 qDebug("Core::dvdTitleChanged: %d", title);
4705}
4706
4707void Core::durationChanged(double length) {
4708 qDebug("Core::durationChanged: %f", length);
4709 if (mdat.duration != length) {
4710 mdat.duration = length;
4711 emit newDuration(length);
4712 }
4713}
4714
4715void Core::askForInfo() {
4716 if (proc->isMPlayer()) {
4717 if ((state() == Playing) && (mdat.filename.startsWith("dvdnav:"))) {
4718 proc->setPausingPrefix(pausing_prefix());
4719 proc->askForLength();
4720 }
4721 }
4722}
4723
4724void Core::dvdnavUpdateMousePos(QPoint pos) {
4725#if 0
4726 bool under_mouse = mplayerwindow->videoLayer()->underMouse();
4727
4728 qDebug("Core::dvdnavUpdateMousePos: %d %d", pos.x(), pos.y());
4729 qDebug("Core::dvdnavUpdateMousePos: state: %d", state());
4730 qDebug("Core::dvdnavUpdateMousePos: filename: %s", mdat.filename.toUtf8().constData());
4731 qDebug("Core::dvdnavUpdateMousePos: dvdnav_title_is_menu: %d", dvdnav_title_is_menu);
4732 qDebug("Core::dvdnavUpdateMousePos: under mouse: %d", under_mouse);
4733#endif
4734 if ((state() == Playing) && (mdat.filename.startsWith("dvdnav:")) && (dvdnav_title_is_menu)) {
4735 //if (under_mouse) {
4736 proc->discSetMousePos(pos.x(), pos.y());
4737 //}
4738 }
4739}
4740
4741void Core::dvdTitleIsMenu() {
4742 qDebug("Core::dvdTitleIsMenu");
4743 dvdnav_title_is_menu = true;
4744}
4745
4746void Core::dvdTitleIsMovie() {
4747 qDebug("Core::dvdTitleIsMovie");
4748 dvdnav_title_is_menu = false;
4749}
4750#endif
4751
4752QString Core::pausing_prefix() {
4753 qDebug("Core::pausing_prefix");
4754
4755#ifdef MPLAYER2_SUPPORT
4756 if (MplayerVersion::isMplayer2()) {
4757 return QString::null;
4758 }
4759 else
4760#endif
4761 if ( (pref->use_pausing_keep_force) &&
4762 (MplayerVersion::isMplayerAtLeast(27665)) )
4763 {
4764 return "pausing_keep_force";
4765 } else {
4766 return "pausing_keep";
4767 }
4768}
4769
4770#ifdef BOOKMARKS
4771void Core::prevBookmark() {
4772 qDebug("Core::prevBookmark");
4773
4774 if (mset.bookmarks.count() > 0) {
4775 QMapIterator<int, QString> i(mset.bookmarks);
4776 i.toBack();
4777 int last_time = i.peekPrevious().key();
4778 while (i.hasPrevious()) {
4779 i.previous();
4780 int time = i.key();
4781 if (time < (mset.current_sec -2)) {
4782 goToSec(time);
4783 return;
4784 }
4785 }
4786 // Go to last bookmark
4787 goToSec(last_time);
4788 }
4789}
4790
4791void Core::nextBookmark() {
4792 qDebug("Core::nextBookmark");
4793
4794 if (mset.bookmarks.count() > 0) {
4795 QMapIterator<int, QString> i(mset.bookmarks);
4796 int first_time = i.peekNext().key();
4797 while (i.hasNext()) {
4798 i.next();
4799 int time = i.key();
4800 if (time > mset.current_sec) {
4801 goToSec(time);
4802 return;
4803 }
4804 }
4805 // Go to first bookmark
4806 goToSec(first_time);
4807 }
4808}
4809#endif
4810
4811#include "moc_core.cpp"
Note: See TracBrowser for help on using the repository browser.