source: smplayer/trunk/src/core.cpp

Last change on this file was 188, checked in by Silvan Scherrer, 8 years ago

SMPlayer: update trunk to version 17.1.0

  • Property svn:eol-style set to LF
File size: 119.8 KB
Line 
1/* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2017 Ricardo Villalba <rvm@users.sourceforge.net>
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, QStringList params) {
927 qDebug() << "Core::openStream:" << name << "params:" << params;
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 mdat.extra_params = params;
961
962 mset.reset();
963
964 #ifdef YOUTUBE_SUPPORT
965 if (PREF_YT_ENABLED) {
966 if (mdat.filename == yt->latestPreferredUrl()) name = yt->origUrl();
967 }
968 #endif
969 // Check if we already have info about this file
970 if (file_settings->existSettingsFor(name, mdat.type)) {
971 qDebug("Core::openStream: we have settings for this stream");
972 restoreSettingsForMedia(name, mdat.type);
973 }
974
975 /* initializeMenus(); */
976
977 initPlaying();
978}
979
980
981void Core::playNewFile(QString file, int seek) {
982 qDebug("Core::playNewFile: '%s'", file.toUtf8().data());
983
984 if (proc->isRunning()) {
985 stopMplayer();
986 we_are_restarting = false;
987 }
988
989 // Save data of previous file:
990 saveMediaInfo();
991
992 mdat.reset();
993 mdat.filename = file;
994 mdat.type = TYPE_FILE;
995
996 int old_volume = mset.volume;
997 mset.reset();
998
999 // Check if we already have info about this file
1000 if (file_settings->existSettingsFor(file, mdat.type)) {
1001 qDebug("Core::playNewFile: we have settings for this file");
1002 restoreSettingsForMedia(file, mdat.type);
1003 } else {
1004 // Recover volume
1005 mset.volume = old_volume;
1006 }
1007
1008 /* initializeMenus(); */
1009
1010 qDebug("Core::playNewFile: volume: %d, old_volume: %d", mset.volume, old_volume);
1011 initPlaying(seek);
1012}
1013
1014
1015void Core::restartPlay() {
1016 we_are_restarting = true;
1017 initPlaying();
1018}
1019
1020void Core::initPlaying(int seek) {
1021 qDebug("Core::initPlaying");
1022
1023 /*
1024 mdat.list();
1025 mset.list();
1026 */
1027
1028 /* updateWidgets(); */
1029
1030 mplayerwindow->hideLogo();
1031
1032 if (proc->isRunning()) {
1033 stopMplayer();
1034 }
1035
1036 int start_sec = (int) mset.current_sec;
1037 if (seek > -1) start_sec = seek;
1038
1039#ifdef YOUTUBE_SUPPORT
1040 if (PREF_YT_ENABLED) {
1041 // Avoid to pass to mplayer the youtube page url
1042 if (mdat.type == TYPE_STREAM) {
1043 if (mdat.filename == yt->origUrl()) {
1044 mdat.filename = yt->latestPreferredUrl();
1045 }
1046 }
1047 }
1048#endif
1049
1050 startMplayer( mdat.filename, start_sec );
1051}
1052
1053// This is reached when a new video has just started playing
1054// and maybe we need to give some defaults
1055void Core::newMediaPlaying() {
1056 qDebug("Core::newMediaPlaying: --- start ---");
1057
1058 QString file = mdat.filename;
1059 int type = mdat.type;
1060 mdat = proc->mediaData();
1061 mdat.filename = file;
1062 mdat.type = type;
1063
1064 initializeMenus(); // Old
1065
1066 // Copy the demuxer
1067 mset.current_demuxer = mdat.demuxer;
1068
1069 // Video
1070 #if 0
1071 if ( (mset.current_video_id == MediaSettings::NoneSelected) &&
1072 (mdat.videos.numItems() > 0) )
1073 {
1074 changeVideo( mdat.videos.itemAt(0).ID(), false ); // Don't allow to restart
1075 }
1076 #endif
1077
1078#if !DELAYED_AUDIO_SETUP_ON_STARTUP && !NOTIFY_AUDIO_CHANGES
1079 // First audio if none selected
1080 if ( (mset.current_audio_id == MediaSettings::NoneSelected) &&
1081 (mdat.audios.numItems() > 0) )
1082 {
1083 // Don't set mset.current_audio_id here! changeAudio will do.
1084 // Otherwise changeAudio will do nothing.
1085
1086 int audio = mdat.audios.itemAt(0).ID(); // First one
1087 if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) {
1088 audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID();
1089 }
1090
1091 // Check if one of the audio tracks is the user preferred.
1092 if (!pref->audio_lang.isEmpty()) {
1093 int res = mdat.audios.findLang( pref->audio_lang );
1094 if (res != -1) audio = res;
1095 }
1096
1097 // Change the audio without restarting mplayer, it's not
1098 // safe to do it here.
1099 changeAudio( audio, false );
1100
1101 }
1102#endif
1103
1104#if !NOTIFY_SUB_CHANGES
1105 // Subtitles
1106 if (mset.external_subtitles.isEmpty()) {
1107 if (pref->autoload_sub) {
1108 //Select first subtitle if none selected
1109 if (mset.current_sub_id == MediaSettings::NoneSelected) {
1110 int sub = mdat.subs.selectOne( pref->subtitle_lang, pref->initial_subtitle_track-1 );
1111 changeSubtitle( sub );
1112 }
1113 } else {
1114 changeSubtitle( MediaSettings::SubNone );
1115 }
1116 }
1117#endif
1118
1119 mdat.initialized = true;
1120
1121 // MPlayer doesn't display the length in ID_LENGTH for audio CDs...
1122 if ((mdat.duration == 0) && (mdat.type == TYPE_AUDIO_CD)) {
1123 /*
1124 qDebug(" *** get duration here from title info *** ");
1125 qDebug(" *** current title: %d", mset.current_title_id );
1126 */
1127 if (mset.current_title_id > 0) {
1128 mdat.duration = mdat.titles.item(mset.current_title_id).duration();
1129 }
1130 }
1131
1132 /* updateWidgets(); */
1133
1134 mdat.list();
1135 mset.list();
1136
1137 qDebug("Core::newMediaPlaying: --- end ---");
1138}
1139
1140void Core::finishRestart() {
1141 qDebug("Core::finishRestart: --- start ---");
1142
1143 if (!we_are_restarting) {
1144 newMediaPlaying();
1145 //QTimer::singleShot(1000, this, SIGNAL(mediaStartPlay()));
1146 emit mediaStartPlay();
1147 }
1148
1149 if (we_are_restarting) {
1150 // Update info about codecs and demuxer
1151 mdat.video_codec = proc->mediaData().video_codec;
1152 mdat.audio_codec = proc->mediaData().audio_codec;
1153 mdat.demuxer = proc->mediaData().demuxer;
1154 }
1155
1156 if (forced_titles.contains(mdat.filename)) {
1157 mdat.clip_name = forced_titles[mdat.filename];
1158 }
1159
1160#ifdef YOUTUBE_SUPPORT
1161 if (PREF_YT_ENABLED) {
1162 // Change the real url with the youtube page url and set the title
1163 if (mdat.type == TYPE_STREAM) {
1164 if (mdat.filename == yt->latestPreferredUrl()) {
1165 mdat.filename = yt->origUrl();
1166 mdat.stream_title = yt->urlTitle();
1167 }
1168 }
1169 }
1170#endif
1171
1172#if !NOTIFY_SUB_CHANGES
1173 // Subtitles
1174 //if (we_are_restarting) {
1175 if ( (just_loaded_external_subs) || (just_unloaded_external_subs) ) {
1176 qDebug("Core::finishRestart: processing new subtitles");
1177
1178 // Just to simplify things
1179 if (mset.current_sub_id == MediaSettings::NoneSelected) {
1180 mset.current_sub_id = MediaSettings::SubNone;
1181 }
1182
1183 // Save current sub
1184 SubData::Type type;
1185 int ID;
1186 int old_item = -1;
1187 if ( mset.current_sub_id != MediaSettings::SubNone ) {
1188 old_item = mset.current_sub_id;
1189 type = mdat.subs.itemAt(old_item).type();
1190 ID = mdat.subs.itemAt(old_item).ID();
1191 }
1192
1193 // Use the subtitle info from mplayerprocess
1194 qDebug( "Core::finishRestart: copying sub data from proc to mdat");
1195 mdat.subs = proc->mediaData().subs;
1196 initializeMenus();
1197 int item = MediaSettings::SubNone;
1198
1199 // Try to recover old subtitle
1200 if (just_unloaded_external_subs) {
1201 if (old_item > -1) {
1202 int new_item = mdat.subs.find(type, ID);
1203 if (new_item > -1) item = new_item;
1204 }
1205 }
1206
1207 // If we've just loaded a subtitle file
1208 // select one if the user wants to autoload
1209 // one subtitle
1210 if (just_loaded_external_subs) {
1211 if ( (pref->autoload_sub) && (item == MediaSettings::SubNone) ) {
1212 qDebug("Core::finishRestart: cannot find previous subtitle");
1213 qDebug("Core::finishRestart: selecting a new one");
1214 item = mdat.subs.selectOne( pref->subtitle_lang );
1215 }
1216 }
1217 changeSubtitle( item );
1218 just_loaded_external_subs = false;
1219 just_unloaded_external_subs = false;
1220 } else {
1221 // Normal restart, subtitles haven't changed
1222 // Recover current subtitle
1223 changeSubtitle( mset.current_sub_id );
1224 changeSecondarySubtitle( mset.current_secondary_sub_id );
1225 }
1226#endif
1227
1228 we_are_restarting = false;
1229
1230 changeAspectRatio(mset.aspect_ratio_id);
1231
1232 if (pref->mplayer_additional_options.contains("-volume")) {
1233 qDebug("Core::finishRestart: don't set volume since -volume is used");
1234 } else {
1235 // Code to set the volume, used when mplayer didn't have the -volume option
1236 /*
1237 if (pref->global_volume) {
1238 bool was_muted = pref->mute;
1239 setVolume( pref->volume, true);
1240 if (was_muted) mute(true);
1241 } else {
1242 bool was_muted = mset.mute;
1243 setVolume( mset.volume, true );
1244 if (was_muted) mute(true);
1245 }
1246 */
1247 int vol = (pref->global_volume ? pref->volume : mset.volume);
1248 volumeChanged(vol);
1249
1250 if (proc->isMPlayer() && pref->mute) {
1251 // Set mute here because mplayer doesn't have an option to set mute from the command line
1252 mute(true);
1253 }
1254 }
1255
1256#if 0
1257// Old. Gamma already set with option -gamma
1258 if (pref->change_video_equalizer_on_startup && (mset.gamma != 0)) {
1259 int gamma = mset.gamma;
1260 mset.gamma = -1000; // if mset.gamma == new value, mset.gamma is not changed!
1261 setGamma( gamma );
1262 }
1263#endif
1264 // Hack to be sure that the equalizers are up to date
1265 emit videoEqualizerNeedsUpdate();
1266 emit audioEqualizerNeedsUpdate();
1267
1268 changeZoom(mset.zoom_factor);
1269
1270 // Toggle subtitle visibility
1271 changeSubVisibility(pref->sub_visibility);
1272
1273 // A-B marker
1274 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
1275
1276 // Initialize the OSD level
1277 QTimer::singleShot(pref->osd_delay, this, SLOT(initializeOSD()));
1278
1279 emit mediaLoaded();
1280 emit mediaInfoChanged();
1281 emit newDuration(mdat.duration);
1282
1283 emit mediaDataReceived(mdat);
1284
1285 updateWidgets(); // New
1286
1287 qDebug("Core::finishRestart: --- end ---");
1288}
1289
1290void Core::initializeOSD() {
1291 changeOSD(pref->osd);
1292}
1293
1294void Core::stop()
1295{
1296 qDebug("Core::stop");
1297 qDebug("Core::stop: state: %s", stateToString().toUtf8().data());
1298
1299 if (state()==Stopped) {
1300 // if pressed stop twice, reset video to the beginning
1301 qDebug("Core::stop: mset.current_sec: %f", mset.current_sec);
1302 mset.current_sec = 0;
1303 qDebug("Core::stop: mset.current_sec set to 0");
1304 emit showTime( mset.current_sec );
1305 #ifdef SEEKBAR_RESOLUTION
1306 emit positionChanged( 0 );
1307 #else
1308 emit posChanged( 0 );
1309 #endif
1310 //updateWidgets();
1311 }
1312
1313 stopMplayer();
1314 emit mediaStoppedByUser();
1315
1316 if (pref->reset_stop) {
1317 mset.current_sec = 0;
1318 emit showTime( mset.current_sec );
1319 #ifdef SEEKBAR_RESOLUTION
1320 emit positionChanged( 0 );
1321 #else
1322 emit posChanged( 0 );
1323 #endif
1324 }
1325}
1326
1327
1328void Core::play() {
1329 qDebug("Core::play");
1330
1331 if ((proc->isRunning()) && (state()==Paused)) {
1332 proc->setPause(false);
1333 }
1334 else
1335 if ((proc->isRunning()) && (state()==Playing)) {
1336 // nothing to do, continue playing
1337 }
1338 else {
1339 // if we're stopped, play it again
1340 if ( !mdat.filename.isEmpty() ) {
1341 /*
1342 qDebug( "current_sec: %f, duration: %f", mset.current_sec, mdat.duration);
1343 if ( (floor(mset.current_sec)) >= (floor(mdat.duration)) ) {
1344 mset.current_sec = 0;
1345 }
1346 */
1347 restartPlay();
1348 } else {
1349 emit noFileToPlay();
1350 }
1351 }
1352}
1353
1354void Core::pause_and_frame_step() {
1355 qDebug("Core::pause_and_frame_step");
1356
1357 if (proc->isRunning()) {
1358 if (state() == Paused) {
1359 proc->frameStep();
1360 } else {
1361 proc->setPause(true);
1362 }
1363 }
1364}
1365
1366void Core::pause() {
1367 qDebug("Core::pause: current state: %s", stateToString().toUtf8().data());
1368
1369 if (proc->isRunning()) {
1370 // Pauses and unpauses
1371 if (state() == Paused) proc->setPause(false); else proc->setPause(true);
1372 }
1373}
1374
1375void Core::play_or_pause() {
1376 if (proc->isRunning()) {
1377 pause();
1378 } else {
1379 play();
1380 }
1381}
1382
1383void Core::frameStep() {
1384 qDebug("Core::frameStep");
1385
1386 if (proc->isRunning()) {
1387 proc->frameStep();
1388 }
1389}
1390
1391void Core::frameBackStep() {
1392 qDebug("Core::frameBackStep");
1393
1394 if (proc->isRunning()) {
1395 proc->frameBackStep();
1396 }
1397}
1398
1399void Core::screenshot() {
1400 qDebug("Core::screenshot");
1401
1402 if (!pref->screenshot_directory.isEmpty()
1403 /* && QFileInfo(pref->screenshot_directory).isDir() */)
1404 {
1405 proc->setPausingPrefix(pausing_prefix());
1406 proc->takeScreenshot(PlayerProcess::Single, pref->subtitles_on_screenshots);
1407 qDebug("Core::screenshot: taken screenshot");
1408 } else {
1409 qDebug("Core::screenshot: error: directory for screenshots not valid");
1410 emit showMessage( tr("Screenshot NOT taken, folder not configured") );
1411 }
1412}
1413
1414void Core::screenshots() {
1415 qDebug("Core::screenshots");
1416
1417 if (!pref->screenshot_directory.isEmpty()
1418 /* && QFileInfo(pref->screenshot_directory).isDir() */)
1419 {
1420 proc->takeScreenshot(PlayerProcess::Multiple, pref->subtitles_on_screenshots);
1421 } else {
1422 qDebug("Core::screenshots: error: directory for screenshots not valid");
1423 emit showMessage( tr("Screenshots NOT taken, folder not configured") );
1424 }
1425}
1426
1427#ifdef CAPTURE_STREAM
1428void Core::switchCapturing() {
1429 qDebug("Core::switchCapturing");
1430 proc->switchCapturing();
1431}
1432#endif
1433
1434void Core::processFinished()
1435{
1436 qDebug("Core::processFinished");
1437 qDebug("Core::processFinished: we_are_restarting: %d", we_are_restarting);
1438
1439 //mset.current_sec = 0;
1440
1441 if (!we_are_restarting) {
1442 qDebug("Core::processFinished: play has finished!");
1443 setState(Stopped);
1444 //emit stateChanged(state());
1445 }
1446
1447 int exit_code = proc->exitCode();
1448 qDebug("Core::processFinished: exit_code: %d", exit_code);
1449 if (exit_code != 0) {
1450 setState(Stopped);
1451 emit stateChanged(Stopped);
1452 emit mplayerFinishedWithError(exit_code);
1453 }
1454}
1455
1456void Core::fileReachedEnd() {
1457 /*
1458 if (mdat.type == TYPE_VCD) {
1459 // If the first vcd title has nothing, it doesn't start to play
1460 // and menus are not initialized.
1461 initializeMenus();
1462 }
1463 */
1464
1465 // If we're at the end of the movie, reset to 0
1466 mset.current_sec = 0;
1467 updateWidgets();
1468
1469 emit mediaFinished();
1470}
1471
1472#if SEEKBAR_RESOLUTION
1473void Core::goToPosition(int value) {
1474 qDebug("Core::goToPosition: value: %d", value);
1475
1476 if (pref->relative_seeking) {
1477 goToPos( (double) value / (SEEKBAR_RESOLUTION / 100) );
1478 }
1479 else {
1480 if (mdat.duration > 0) {
1481 int jump_time = (int) mdat.duration * value / SEEKBAR_RESOLUTION;
1482 goToSec(jump_time);
1483 }
1484 }
1485}
1486
1487void Core::goToPos(double perc) {
1488 qDebug("Core::goToPos: per: %f", perc);
1489 seek_cmd(perc, 1);
1490}
1491#else
1492void Core::goToPos(int perc) {
1493 qDebug("Core::goToPos: per: %d", perc);
1494 seek_cmd(perc, 1);
1495}
1496#endif
1497
1498
1499void Core::startMplayer( QString file, double seek ) {
1500 qDebug("Core::startMplayer");
1501
1502 if (file.isEmpty()) {
1503 qWarning("Core:startMplayer: file is empty!");
1504 return;
1505 }
1506
1507 if (proc->isRunning()) {
1508 qWarning("Core::startMplayer: MPlayer still running!");
1509 return;
1510 }
1511
1512#ifdef YOUTUBE_SUPPORT
1513 // Stop any pending request
1514 #if 0
1515 qDebug("Core::startMplayer: yt state: %d", yt->state());
1516 if (yt->state() != QHttp::Unconnected) {
1517 //yt->abort(); /* Make the app to crash, don't know why */
1518 }
1519 #endif
1520 yt->close();
1521#endif
1522
1523 // DVD
1524 QString dvd_folder;
1525 int dvd_title = -1;
1526 if (mdat.type==TYPE_DVD) {
1527 DiscData disc_data = DiscName::split(file);
1528 dvd_folder = disc_data.device;
1529 if (dvd_folder.isEmpty()) dvd_folder = pref->dvd_device;
1530 dvd_title = disc_data.title;
1531 file = disc_data.protocol + "://";
1532 if (dvd_title > -1) file += QString::number(dvd_title);
1533 }
1534
1535 // Check URL playlist
1536 bool url_is_playlist = false;
1537 if (file.endsWith("|playlist")) {
1538 url_is_playlist = true;
1539 file = file.remove("|playlist");
1540 } else {
1541 QUrl url(file);
1542 qDebug("Core::startMplayer: checking if stream is a playlist");
1543 qDebug("Core::startMplayer: url path: '%s'", url.path().toUtf8().constData());
1544
1545 if (url.scheme().toLower() != "ffmpeg") {
1546 QRegExp rx("\\.ram$|\\.asx$|\\.m3u$|\\.m3u8$|\\.pls$", Qt::CaseInsensitive);
1547 url_is_playlist = (rx.indexIn(url.path()) != -1);
1548 }
1549 }
1550 qDebug("Core::startMplayer: url_is_playlist: %d", url_is_playlist);
1551
1552 // Hack: don't use -ss with m3u(8) streams
1553 if (mdat.type == TYPE_STREAM) {
1554 QString extension = Extensions::extensionFromUrl(file);
1555 qDebug() << "Core::startMplayer: URL extension:" << extension;
1556 if (extension.contains("m3u")) {
1557 seek = 0;
1558 }
1559 }
1560
1561 // Check if a m4a file exists with the same name of file, in that cause if will be used as audio
1562 if (pref->autoload_m4a && mset.external_audio.isEmpty()) {
1563 QFileInfo fi(file);
1564 if (fi.exists() && !fi.isDir()) {
1565 if (fi.suffix().toLower() == "mp4") {
1566 QString file2 = fi.path() + "/" + fi.completeBaseName() + ".m4a";
1567 //qDebug("Core::startMplayer: file2: %s", file2.toUtf8().constData());
1568 if (!QFile::exists(file2)) {
1569 // Check for upper case
1570 file2 = fi.path() + "/" + fi.completeBaseName() + ".M4A";
1571 }
1572 if (QFile::exists(file2)) {
1573 qDebug("Core::startMplayer: found %s, so it will be used as audio file", file2.toUtf8().constData());
1574 mset.external_audio = file2;
1575 }
1576 }
1577 }
1578 }
1579
1580
1581 bool screenshot_enabled = (pref->use_screenshot && !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 proc->setOption("ss", QString::number(seek));
2116 } else {
2117 proc->setOption("ss", QString::number(mset.A_marker));
2118 proc->setOption("endpos", QString::number(mset.B_marker - mset.A_marker));
2119 }
2120 }
2121 else
2122 // If seek < 5 it's better to allow the video to start from the beginning
2123 if ((seek >= 5) && (!mset.loop)) {
2124 proc->setOption("ss", QString::number(seek));
2125 }
2126 }
2127
2128 // Enable the OSD later, to avoid a lot of messages to be
2129 // printed on startup
2130 proc->setOption("osdlevel", "0");
2131
2132 if (pref->use_idx) {
2133 proc->setOption("idx");
2134 }
2135
2136 if (mdat.type == TYPE_STREAM) {
2137 if (pref->prefer_ipv4) {
2138 proc->setOption("prefer-ipv4");
2139 } else {
2140 proc->setOption("prefer-ipv6");
2141 }
2142 }
2143
2144 if (pref->use_correct_pts != Preferences::Detect) {
2145 proc->setOption("correct-pts", (pref->use_correct_pts == Preferences::Enabled));
2146 }
2147
2148 bool force_noslices = false;
2149
2150#ifndef Q_OS_WIN
2151 if (proc->isMPlayer()) {
2152 if ((pref->vdpau.disable_video_filters) && (pref->vo.startsWith("vdpau"))) {
2153 qDebug("Core::startMplayer: using vdpau, video filters are ignored");
2154 goto end_video_filters;
2155 }
2156 } else {
2157 // MPV
2158 if (!pref->hwdec.isEmpty() && pref->hwdec != "no") {
2159 qDebug("Core::startMplayer: hardware decoding is enabled. The video filters will be ignored");
2160 goto end_video_filters;
2161 }
2162 }
2163#endif
2164
2165 // Video filters:
2166 // Phase
2167 if (mset.phase_filter) {
2168 proc->addVF("phase", "A");
2169 }
2170
2171 // Deinterlace
2172 if (mset.current_deinterlacer != MediaSettings::NoDeinterlace) {
2173 switch (mset.current_deinterlacer) {
2174 case MediaSettings::L5: proc->addVF("l5"); break;
2175 case MediaSettings::Yadif: proc->addVF("yadif"); break;
2176 case MediaSettings::LB: proc->addVF("lb"); break;
2177 case MediaSettings::Yadif_1: proc->addVF("yadif", "1"); break;
2178 case MediaSettings::Kerndeint: proc->addVF("kerndeint", "5"); break;
2179 }
2180 }
2181
2182 // 3D stereo
2183 if (mset.stereo3d_in != "none" && !mset.stereo3d_out.isEmpty()) {
2184 proc->addStereo3DFilter(mset.stereo3d_in, mset.stereo3d_out);
2185 }
2186
2187 // Denoise
2188 if (mset.current_denoiser != MediaSettings::NoDenoise) {
2189 if (mset.current_denoiser==MediaSettings::DenoiseSoft) {
2190 proc->addVF("hqdn3d", pref->filters->item("denoise_soft").options());
2191 } else {
2192 proc->addVF("hqdn3d", pref->filters->item("denoise_normal").options());
2193 }
2194 }
2195
2196 // Unsharp
2197 if (mset.current_unsharp != 0) {
2198 if (mset.current_unsharp == 1) {
2199 proc->addVF("blur", pref->filters->item("blur").options());
2200 } else {
2201 proc->addVF("sharpen", pref->filters->item("sharpen").options());
2202 }
2203 }
2204
2205 // Deblock
2206 if (mset.deblock_filter) {
2207 proc->addVF("deblock", pref->filters->item("deblock").options());
2208 }
2209
2210 // Dering
2211 if (mset.dering_filter) {
2212 proc->addVF("dering");
2213 }
2214
2215 // Gradfun
2216 if (mset.gradfun_filter) {
2217 proc->addVF("gradfun", pref->filters->item("gradfun").options());
2218 }
2219
2220 // Upscale
2221 if (mset.upscaling_filter) {
2222 int width = DesktopInfo::desktop_size(mplayerwindow).width();
2223 proc->setOption("sws", "9");
2224 proc->addVF("scale", QString::number(width) + ":-2");
2225 }
2226
2227 // Addnoise
2228 if (mset.noise_filter) {
2229 proc->addVF("noise", pref->filters->item("noise").options());
2230 }
2231
2232 // Postprocessing
2233 if (mset.postprocessing_filter) {
2234 proc->addVF("postprocessing");
2235 proc->setOption("autoq", QString::number(pref->autoq));
2236 }
2237
2238
2239
2240 // Letterbox (expand)
2241 if ((mset.add_letterbox)
2242 #ifdef ADD_BLACKBORDERS_FS
2243 || (pref->fullscreen && pref->add_blackborders_on_fullscreen)
2244 #endif
2245 ) {
2246 proc->addVF("expand", QString("aspect=%1").arg( DesktopInfo::desktop_aspectRatio(mplayerwindow)));
2247 }
2248
2249 // Software equalizer
2250 if ( (pref->use_soft_video_eq) ) {
2251 proc->addVF("eq2");
2252 proc->addVF("hue");
2253 if ( (pref->vo == "gl") || (pref->vo == "gl2") || (pref->vo == "gl_tiled")
2254#ifdef Q_OS_WIN
2255 || (pref->vo == "directx:noaccel")
2256#endif
2257 )
2258 {
2259 proc->addVF("scale");
2260 }
2261 }
2262
2263 // Additional video filters, supplied by user
2264 // File
2265 if ( !mset.mplayer_additional_video_filters.isEmpty() ) {
2266 proc->setOption("vf-add", mset.mplayer_additional_video_filters);
2267 }
2268 // Global
2269 if ( !pref->mplayer_additional_video_filters.isEmpty() ) {
2270 proc->setOption("vf-add", pref->mplayer_additional_video_filters);
2271 }
2272
2273 // Filters for subtitles on screenshots
2274 if ((screenshot_enabled) && (pref->subtitles_on_screenshots))
2275 {
2276 if (pref->use_ass_subtitles) {
2277 proc->addVF("subs_on_screenshots", "ass");
2278 } else {
2279 proc->addVF("subs_on_screenshots");
2280 force_noslices = true;
2281 }
2282 }
2283
2284 // Rotate
2285 if (mset.rotate != MediaSettings::NoRotate) {
2286 proc->addVF("rotate", QString::number(mset.rotate));
2287 }
2288
2289 // Flip
2290 if (mset.flip) {
2291 proc->addVF("flip");
2292 }
2293
2294 // Mirror
2295 if (mset.mirror) {
2296 proc->addVF("mirror");
2297 }
2298
2299 // Screenshots
2300 #ifdef MPLAYER_SUPPORT
2301 if (screenshot_enabled && proc->isMPlayer()) {
2302 QString dir = pref->screenshot_directory;
2303 #ifdef Q_OS_WIN
2304 if (pref->use_short_pathnames) dir = Helper::shortPathName(pref->screenshot_directory);
2305 #endif
2306 proc->enableScreenshots(dir);
2307 }
2308 #endif
2309
2310#ifndef Q_OS_WIN
2311 end_video_filters:
2312#endif
2313
2314 #ifdef MPV_SUPPORT
2315 if (screenshot_enabled && proc->isMPV()) {
2316 QString dir = pref->screenshot_directory;
2317 #ifdef Q_OS_WIN
2318 if (pref->use_short_pathnames) dir = Helper::shortPathName(pref->screenshot_directory);
2319 #endif
2320 proc->enableScreenshots(dir, pref->screenshot_template, pref->screenshot_format);
2321 }
2322 #endif
2323
2324 // slices
2325 if ((pref->use_slices) && (!force_noslices)) {
2326 proc->setOption("slices", true);
2327 } else {
2328 proc->setOption("slices", false);
2329 }
2330
2331
2332 // Audio channels
2333 if (mset.audio_use_channels != 0) {
2334 proc->setOption("channels", QString::number(mset.audio_use_channels));
2335 }
2336
2337 if (!pref->use_hwac3) {
2338
2339 // Audio filters
2340 #ifdef MPLAYER_SUPPORT
2341 if (mset.karaoke_filter) {
2342 proc->addAF("karaoke");
2343 }
2344 #endif
2345
2346 // Stereo mode
2347 if (mset.stereo_mode != 0) {
2348 switch (mset.stereo_mode) {
2349 case MediaSettings::Left: proc->addAF("channels", "2:2:0:1:0:0"); break;
2350 case MediaSettings::Right: proc->addAF("channels", "2:2:1:0:1:1"); break;
2351 case MediaSettings::Mono: proc->addAF("pan", "1:0.5:0.5"); break;
2352 case MediaSettings::Reverse: proc->addAF("channels", "2:2:0:1:1:0"); break;
2353 }
2354 }
2355
2356 if (mset.extrastereo_filter) {
2357 proc->addAF("extrastereo");
2358 }
2359
2360 if (mset.volnorm_filter) {
2361 proc->addAF("volnorm", pref->filters->item("volnorm").options());
2362 }
2363
2364 if (proc->isMPlayer()) {
2365 bool use_scaletempo = (pref->use_scaletempo == Preferences::Enabled);
2366 if (pref->use_scaletempo == Preferences::Detect) {
2367 use_scaletempo = (MplayerVersion::isMplayerAtLeast(24924));
2368 }
2369 if (use_scaletempo) {
2370 proc->addAF("scaletempo");
2371 }
2372 } else {
2373 // MPV
2374 proc->setOption("scaletempo", pref->use_scaletempo != Preferences::Disabled);
2375 }
2376
2377 // Audio equalizer
2378 if (pref->use_audio_equalizer) {
2379 AudioEqualizerList l = pref->global_audio_equalizer ? pref->audio_equalizer : mset.audio_equalizer;
2380 proc->addAF("equalizer", Helper::equalizerListToString(l));
2381 }
2382
2383 // Additional audio filters, supplied by user
2384 // File
2385 if ( !pref->mplayer_additional_audio_filters.isEmpty() ) {
2386 proc->setOption("af-add", pref->mplayer_additional_audio_filters);
2387 }
2388 // Global
2389 if ( !mset.mplayer_additional_audio_filters.isEmpty() ) {
2390 proc->setOption("af-add", mset.mplayer_additional_audio_filters);
2391 }
2392 } else {
2393 // Don't use audio filters if using the S/PDIF output
2394 qDebug("Core::startMplayer: audio filters are disabled when using the S/PDIF output!");
2395 }
2396
2397 if (pref->use_soft_vol) {
2398 proc->setOption("softvol", QString::number(pref->softvol_max));
2399 } else {
2400 proc->setOption("softvol", "off");
2401 }
2402
2403#ifdef MPV_SUPPORT
2404 if (mdat.type == TYPE_STREAM) {
2405 if (pref->streaming_type == Preferences::StreamingAuto) {
2406 bool is_youtube = false;
2407 #ifdef YOUTUBE_SUPPORT
2408 if (PREF_YT_ENABLED) is_youtube = (file == yt->latestPreferredUrl());
2409 #endif
2410 qDebug() << "Core::startMplayer: is_youtube:" << is_youtube;
2411 bool enable_sites = !is_youtube;
2412
2413 if (!is_youtube) {
2414 // Check if the URL contains a media extension
2415 QString extension = Extensions::extensionFromUrl(file);
2416 qDebug() << "Core::startMplayer: URL extension:" << extension;
2417 Extensions e;
2418 if (e.allPlayable().contains(extension)) {
2419 qDebug() << "Core::startMplayer: extension found in URL";
2420 enable_sites = false;
2421 }
2422 }
2423 qDebug() << "Core::startMplayer: enable_sites:" << enable_sites;
2424 proc->setOption("enable_streaming_sites_support", enable_sites);
2425 } else {
2426 proc->setOption("enable_streaming_sites_support", pref->streaming_type == Preferences::StreamingYTDL);
2427 }
2428 }
2429#endif
2430
2431#if defined(TV_SUPPORT) && !defined(Q_OS_WIN)
2432 if (proc->isMPV() && file.startsWith("dvb:")) {
2433 QString channels_file = TVList::findChannelsFile();
2434 qDebug("Core::startMplayer: channels_file: %s", channels_file.toUtf8().constData());
2435 if (!channels_file.isEmpty()) proc->setChannelsFile(channels_file);
2436 }
2437#endif
2438
2439#ifdef CAPTURE_STREAM
2440 // Set the capture directory
2441 proc->setCaptureDirectory(pref->capture_directory);
2442#endif
2443
2444 // Load edl file
2445 if (pref->use_edl_files) {
2446 QString edl_f;
2447 QFileInfo f(file);
2448 QString basename = f.path() + "/" + f.completeBaseName();
2449
2450 //qDebug("Core::startMplayer: file basename: '%s'", basename.toUtf8().data());
2451
2452 if (QFile::exists(basename+".edl"))
2453 edl_f = basename+".edl";
2454 else
2455 if (QFile::exists(basename+".EDL"))
2456 edl_f = basename+".EDL";
2457
2458 qDebug("Core::startMplayer: edl file: '%s'", edl_f.toUtf8().data());
2459 if (!edl_f.isEmpty()) {
2460 proc->setOption("edl", edl_f);
2461 }
2462 }
2463
2464 // Process extra params
2465 qDebug() << "Core::startMplayer: extra_params:" << mdat.extra_params;
2466 foreach(QString par, mdat.extra_params) {
2467 QRegExp rx_ref("^http-referrer=(.*)", Qt::CaseInsensitive);
2468 QRegExp rx_agent("^http-user-agent=(.*)", Qt::CaseInsensitive);
2469
2470 if (rx_ref.indexIn(par) > -1) {
2471 QString referrer = rx_ref.cap(1);
2472 qDebug() << "Core::startMplayer: referrer:" << referrer;
2473 proc->setOption("referrer", referrer);
2474 }
2475 else
2476 if (rx_agent.indexIn(par) > -1) {
2477 QString user_agent = rx_agent.cap(1);
2478 qDebug() << "Core::startMplayer: user_agent:" << user_agent;
2479 proc->setOption("user-agent", user_agent);
2480 }
2481 }
2482
2483 // Additional options supplied by the user
2484 // File
2485 if (!mset.mplayer_additional_options.isEmpty()) {
2486 QStringList args = MyProcess::splitArguments(mset.mplayer_additional_options);
2487 for (int n = 0; n < args.count(); n++) {
2488 QString arg = args[n].simplified();
2489 if (!arg.isEmpty()) {
2490 proc->addUserOption(arg);
2491 }
2492 }
2493 }
2494
2495 // Global
2496 if (!pref->mplayer_additional_options.isEmpty()) {
2497 QString additional_options = pref->mplayer_additional_options;
2498 #ifdef MPLAYER2_SUPPORT
2499 // mplayer2 doesn't support -fontconfig and -nofontconfig
2500 if (pref->mplayer_is_mplayer2) {
2501 additional_options.replace("-fontconfig", "");
2502 additional_options.replace("-nofontconfig", "");
2503 }
2504 #endif
2505 QStringList args = MyProcess::splitArguments(additional_options);
2506 for (int n = 0; n < args.count(); n++) {
2507 QString arg = args[n].simplified();
2508 if (!arg.isEmpty()) {
2509 qDebug("arg %d: %s", n, arg.toUtf8().constData());
2510 proc->addUserOption(arg);
2511 }
2512 }
2513
2514 }
2515
2516 // Last checks for the file
2517
2518 // Open https URLs with ffmpeg
2519 #if 0
2520 // It doesn't seem necessary anymore
2521 if (proc->isMPlayer() && file.startsWith("https")) {
2522 file = "ffmpeg://" + file;
2523 }
2524 #endif
2525
2526#if DVDNAV_SUPPORT
2527 if (proc->isMPV() && file.startsWith("dvdnav:")) {
2528 // Hack to open the DVD menu with MPV
2529 file = "dvd://menu";
2530 }
2531#endif
2532
2533#ifdef Q_OS_WIN
2534 if (pref->use_short_pathnames) {
2535 file = Helper::shortPathName(file);
2536 }
2537#endif
2538
2539#ifdef MPLAYER_SUPPORT
2540 if (proc->isMPlayer()) {
2541 proc->setMedia(file, pref->use_playlist_option ? url_is_playlist : false);
2542 } else
2543#endif
2544 {
2545 proc->setMedia(file, false); // Don't use playlist with mpv
2546 }
2547
2548 // It seems the loop option must be after the filename
2549 if (mset.loop) {
2550 proc->setOption("loop", "0");
2551 }
2552
2553 emit aboutToStartPlaying();
2554
2555 QString commandline = proc->arguments().join(" ");
2556 qDebug("Core::startMplayer: command: '%s'", commandline.toUtf8().data());
2557
2558 //Log command
2559 QString line_for_log = commandline + "\n";
2560 emit logLineAvailable(line_for_log);
2561
2562 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2563 if ((pref->use_proxy) && (pref->proxy_type == QNetworkProxy::HttpProxy) && (!pref->proxy_host.isEmpty())) {
2564 QString proxy = QString("http://%1:%2@%3:%4").arg(pref->proxy_username).arg(pref->proxy_password).arg(pref->proxy_host).arg(pref->proxy_port);
2565 env.insert("http_proxy", proxy);
2566 }
2567 //qDebug("Core::startMplayer: env: %s", env.toStringList().join(",").toUtf8().constData());
2568 #ifdef FONTS_HACK
2569 if (!pref->use_windowsfontdir) {
2570 env.insert("FONTCONFIG_FILE", Paths::configPath() + "/fonts.conf");
2571 }
2572 #endif
2573 proc->setProcessEnvironment(env);
2574
2575 if ( !proc->start() ) {
2576 // error handling
2577 qWarning("Core::startMplayer: mplayer process didn't start");
2578 }
2579
2580}
2581
2582void Core::stopMplayer() {
2583 qDebug("Core::stopMplayer");
2584
2585 if (!proc->isRunning()) {
2586 qWarning("Core::stopMplayer: mplayer is not running!");
2587 return;
2588 }
2589
2590#ifdef Q_OS_OS2
2591 QEventLoop eventLoop;
2592
2593 connect(proc, SIGNAL(processExited()), &eventLoop, SLOT(quit()));
2594
2595 proc->quit();
2596
2597 QTimer::singleShot(5000, &eventLoop, SLOT(quit()));
2598 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
2599
2600 if (proc->isRunning()) {
2601 qWarning("Core::stopMplayer: process didn't finish. Killing it...");
2602 proc->kill();
2603 }
2604#else
2605 proc->quit();
2606
2607 qDebug("Core::stopMplayer: Waiting mplayer to finish...");
2608 if (!proc->waitForFinished(pref->time_to_kill_mplayer)) {
2609 qWarning("Core::stopMplayer: process didn't finish. Killing it...");
2610 proc->kill();
2611 }
2612#endif
2613
2614 qDebug("Core::stopMplayer: Finished. (I hope)");
2615}
2616
2617
2618void Core::goToSec( double sec ) {
2619 qDebug("Core::goToSec: %f", sec);
2620
2621 if (sec < 0) sec = 0;
2622 if (sec > mdat.duration ) sec = mdat.duration - 20;
2623 seek_cmd(sec, 2);
2624}
2625
2626
2627void Core::seek(int secs) {
2628 qDebug("Core::seek: %d", secs);
2629 if ( (proc->isRunning()) && (secs!=0) ) {
2630 seek_cmd(secs, 0);
2631 }
2632}
2633
2634void Core::seek_cmd(double secs, int mode) {
2635 proc->seek(secs, mode, pref->precise_seeking);
2636}
2637
2638void Core::sforward() {
2639 qDebug("Core::sforward");
2640 seek( pref->seeking1 ); // +10s
2641}
2642
2643void Core::srewind() {
2644 qDebug("Core::srewind");
2645 seek( -pref->seeking1 ); // -10s
2646}
2647
2648
2649void Core::forward() {
2650 qDebug("Core::forward");
2651 seek( pref->seeking2 ); // +1m
2652}
2653
2654
2655void Core::rewind() {
2656 qDebug("Core::rewind");
2657 seek( -pref->seeking2 ); // -1m
2658}
2659
2660
2661void Core::fastforward() {
2662 qDebug("Core::fastforward");
2663 seek( pref->seeking3 ); // +10m
2664}
2665
2666
2667void Core::fastrewind() {
2668 qDebug("Core::fastrewind");
2669 seek( -pref->seeking3 ); // -10m
2670}
2671
2672void Core::forward(int secs) {
2673 qDebug("Core::forward: %d", secs);
2674 seek(secs);
2675}
2676
2677void Core::rewind(int secs) {
2678 qDebug("Core::rewind: %d", secs);
2679 seek(-secs);
2680}
2681
2682#ifdef MPV_SUPPORT
2683void Core::seekToNextSub() {
2684 qDebug("Core::seekToNextSub");
2685 proc->seekSub(1);
2686}
2687
2688void Core::seekToPrevSub() {
2689 qDebug("Core::seekToPrevSub");
2690 proc->seekSub(-1);
2691}
2692#endif
2693
2694void Core::wheelUp() {
2695 qDebug("Core::wheelUp");
2696 switch (pref->wheel_function) {
2697 case Preferences::Volume : incVolume(); break;
2698 case Preferences::Zoom : incZoom(); break;
2699 case Preferences::Seeking : pref->wheel_function_seeking_reverse ? rewind( pref->seeking4 ) : forward( pref->seeking4 ); break;
2700 case Preferences::ChangeSpeed : incSpeed10(); break;
2701 default : {} // do nothing
2702 }
2703}
2704
2705void Core::wheelDown() {
2706 qDebug("Core::wheelDown");
2707 switch (pref->wheel_function) {
2708 case Preferences::Volume : decVolume(); break;
2709 case Preferences::Zoom : decZoom(); break;
2710 case Preferences::Seeking : pref->wheel_function_seeking_reverse ? forward( pref->seeking4 ) : rewind( pref->seeking4 ); break;
2711 case Preferences::ChangeSpeed : decSpeed10(); break;
2712 default : {} // do nothing
2713 }
2714}
2715
2716void Core::setAMarker() {
2717 setAMarker((int)mset.current_sec);
2718}
2719
2720void Core::setAMarker(int sec) {
2721 qDebug("Core::setAMarker: %d", sec);
2722
2723 mset.A_marker = sec;
2724 displayMessage( tr("\"A\" marker set to %1").arg(Helper::formatTime(sec)) );
2725
2726 if (proc->isMPV()) {
2727 if (mset.loop) proc->setAMarker(sec);
2728 } else {
2729 // MPlayer
2730 if (mset.B_marker > mset.A_marker) {
2731 if (proc->isRunning()) restartPlay();
2732 }
2733 }
2734
2735 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
2736}
2737
2738void Core::setBMarker() {
2739 setBMarker((int)mset.current_sec);
2740}
2741
2742void Core::setBMarker(int sec) {
2743 qDebug("Core::setBMarker: %d", sec);
2744
2745 mset.B_marker = sec;
2746 displayMessage( tr("\"B\" marker set to %1").arg(Helper::formatTime(sec)) );
2747
2748 if (proc->isMPV()) {
2749 if (mset.loop) proc->setBMarker(sec);
2750 } else {
2751 // MPlayer
2752 if ((mset.A_marker > -1) && (mset.A_marker < mset.B_marker)) {
2753 if (proc->isRunning()) restartPlay();
2754 }
2755 }
2756
2757 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
2758}
2759
2760void Core::clearABMarkers() {
2761 qDebug("Core::clearABMarkers");
2762
2763 if ((mset.A_marker != -1) || (mset.B_marker != -1)) {
2764 mset.A_marker = -1;
2765 mset.B_marker = -1;
2766 displayMessage( tr("A-B markers cleared") );
2767 if (proc->isMPV()) {
2768 proc->clearABMarkers();
2769 } else {
2770 // MPlayer
2771 if (proc->isRunning()) restartPlay();
2772 }
2773 }
2774
2775 emit ABMarkersChanged(mset.A_marker, mset.B_marker);
2776}
2777
2778void Core::toggleRepeat() {
2779 qDebug("Core::toggleRepeat");
2780 toggleRepeat( !mset.loop );
2781}
2782
2783void Core::toggleRepeat(bool b) {
2784 qDebug("Core::toggleRepeat: %d", b);
2785 if ( mset.loop != b ) {
2786 mset.loop = b;
2787 if (MplayerVersion::isMplayerAtLeast(23747)) {
2788 // Use slave command
2789 int v = -1; // no loop
2790 if (mset.loop) v = 0; // infinite loop
2791 if (proc->isMPV()) {
2792 // Enable A-B markers
2793 proc->clearABMarkers();
2794 if (b) {
2795 if (mset.A_marker > -1) proc->setAMarker(mset.A_marker);
2796 if (mset.B_marker > -1) proc->setBMarker(mset.B_marker);
2797 }
2798 }
2799 proc->setLoop(v);
2800 } else {
2801 // Restart mplayer
2802 if (proc->isRunning()) restartPlay();
2803 }
2804 }
2805}
2806
2807
2808// Audio filters
2809#ifdef MPLAYER_SUPPORT
2810void Core::toggleKaraoke() {
2811 toggleKaraoke( !mset.karaoke_filter );
2812}
2813
2814void Core::toggleKaraoke(bool b) {
2815 qDebug("Core::toggleKaraoke: %d", b);
2816 if (b != mset.karaoke_filter) {
2817 mset.karaoke_filter = b;
2818 if (MplayerVersion::isMplayerAtLeast(31030)) {
2819 // Change filter without restarting
2820 proc->enableKaraoke(b);
2821 } else {
2822 restartPlay();
2823 }
2824 }
2825}
2826#endif
2827
2828void Core::toggleExtrastereo() {
2829 toggleExtrastereo( !mset.extrastereo_filter );
2830}
2831
2832void Core::toggleExtrastereo(bool b) {
2833 qDebug("Core::toggleExtrastereo: %d", b);
2834 if (b != mset.extrastereo_filter) {
2835 mset.extrastereo_filter = b;
2836 if (MplayerVersion::isMplayerAtLeast(31030)) {
2837 // Change filter without restarting
2838 proc->enableExtrastereo(b);
2839 } else {
2840 restartPlay();
2841 }
2842 }
2843}
2844
2845void Core::toggleVolnorm() {
2846 toggleVolnorm( !mset.volnorm_filter );
2847}
2848
2849void Core::toggleVolnorm(bool b) {
2850 qDebug("Core::toggleVolnorm: %d", b);
2851 if (b != mset.volnorm_filter) {
2852 mset.volnorm_filter = b;
2853 if (MplayerVersion::isMplayerAtLeast(31030)) {
2854 // Change filter without restarting
2855 QString f = pref->filters->item("volnorm").filter();
2856 proc->enableVolnorm(b, pref->filters->item("volnorm").options());
2857 } else {
2858 restartPlay();
2859 }
2860 }
2861}
2862
2863void Core::setAudioChannels(int channels) {
2864 qDebug("Core::setAudioChannels:%d", channels);
2865 if (channels != mset.audio_use_channels ) {
2866 mset.audio_use_channels = channels;
2867 restartPlay();
2868 }
2869}
2870
2871void Core::setStereoMode(int mode) {
2872 qDebug("Core::setStereoMode:%d", mode);
2873 if (mode != mset.stereo_mode ) {
2874 mset.stereo_mode = mode;
2875 restartPlay();
2876 }
2877}
2878
2879
2880// Video filters
2881
2882#define CHANGE_VF(Filter, Enable, Option) \
2883 if (proc->isMPV()) { \
2884 proc->changeVF(Filter, Enable, Option); \
2885 } else { \
2886 restartPlay(); \
2887 }
2888
2889void Core::toggleFlip() {
2890 qDebug("Core::toggleFlip");
2891 toggleFlip( !mset.flip );
2892}
2893
2894void Core::toggleFlip(bool b) {
2895 qDebug("Core::toggleFlip: %d", b);
2896 if (mset.flip != b) {
2897 mset.flip = b;
2898 CHANGE_VF("flip", b, QVariant());
2899 }
2900}
2901
2902void Core::toggleMirror() {
2903 qDebug("Core::toggleMirror");
2904 toggleMirror( !mset.mirror );
2905}
2906
2907void Core::toggleMirror(bool b) {
2908 qDebug("Core::toggleMirror: %d", b);
2909 if (mset.mirror != b) {
2910 mset.mirror = b;
2911 CHANGE_VF("mirror", b, QVariant());
2912 }
2913}
2914
2915void Core::toggleAutophase() {
2916 toggleAutophase( !mset.phase_filter );
2917}
2918
2919void Core::toggleAutophase( bool b ) {
2920 qDebug("Core::toggleAutophase: %d", b);
2921 if ( b != mset.phase_filter) {
2922 mset.phase_filter = b;
2923 CHANGE_VF("phase", b, "A");
2924 }
2925}
2926
2927void Core::toggleDeblock() {
2928 toggleDeblock( !mset.deblock_filter );
2929}
2930
2931void Core::toggleDeblock(bool b) {
2932 qDebug("Core::toggleDeblock: %d", b);
2933 if ( b != mset.deblock_filter ) {
2934 mset.deblock_filter = b;
2935 CHANGE_VF("deblock", b, pref->filters->item("deblock").options());
2936 }
2937}
2938
2939void Core::toggleDering() {
2940 toggleDering( !mset.dering_filter );
2941}
2942
2943void Core::toggleDering(bool b) {
2944 qDebug("Core::toggleDering: %d", b);
2945 if ( b != mset.dering_filter) {
2946 mset.dering_filter = b;
2947 CHANGE_VF("dering", b, QVariant());
2948 }
2949}
2950
2951void Core::toggleGradfun() {
2952 toggleGradfun( !mset.gradfun_filter );
2953}
2954
2955void Core::toggleGradfun(bool b) {
2956 qDebug("Core::toggleGradfun: %d", b);
2957 if ( b != mset.gradfun_filter) {
2958 mset.gradfun_filter = b;
2959 CHANGE_VF("gradfun", b, pref->filters->item("gradfun").options());
2960 }
2961}
2962
2963void Core::toggleNoise() {
2964 toggleNoise( !mset.noise_filter );
2965}
2966
2967void Core::toggleNoise(bool b) {
2968 qDebug("Core::toggleNoise: %d", b);
2969 if ( b != mset.noise_filter ) {
2970 mset.noise_filter = b;
2971 CHANGE_VF("noise", b, QVariant());
2972 }
2973}
2974
2975void Core::togglePostprocessing() {
2976 togglePostprocessing( !mset.postprocessing_filter );
2977}
2978
2979void Core::togglePostprocessing(bool b) {
2980 qDebug("Core::togglePostprocessing: %d", b);
2981 if ( b != mset.postprocessing_filter ) {
2982 mset.postprocessing_filter = b;
2983 CHANGE_VF("postprocessing", b, QVariant());
2984 }
2985}
2986
2987void Core::changeDenoise(int id) {
2988 qDebug( "Core::changeDenoise: %d", id );
2989 if (id != mset.current_denoiser) {
2990 if (proc->isMPlayer()) {
2991 mset.current_denoiser = id;
2992 restartPlay();
2993 } else {
2994 // MPV
2995 QString dsoft = pref->filters->item("denoise_soft").options();
2996 QString dnormal = pref->filters->item("denoise_normal").options();
2997 // Remove previous filter
2998 switch (mset.current_denoiser) {
2999 case MediaSettings::DenoiseSoft: proc->changeVF("hqdn3d", false, dsoft); break;
3000 case MediaSettings::DenoiseNormal: proc->changeVF("hqdn3d", false, dnormal); break;
3001 }
3002 // New filter
3003 mset.current_denoiser = id;
3004 switch (mset.current_denoiser) {
3005 case MediaSettings::DenoiseSoft: proc->changeVF("hqdn3d", true, dsoft); break;
3006 case MediaSettings::DenoiseNormal: proc->changeVF("hqdn3d", true, dnormal); break;
3007 }
3008 }
3009 }
3010}
3011
3012void Core::changeUnsharp(int id) {
3013 qDebug( "Core::changeUnsharp: %d", id );
3014 if (id != mset.current_unsharp) {
3015 if (proc->isMPlayer()) {
3016 mset.current_unsharp = id;
3017 restartPlay();
3018 } else {
3019 // MPV
3020 // Remove previous filter
3021 switch (mset.current_unsharp) {
3022 // Current is blur
3023 case 1: proc->changeVF("blur", false); break;
3024 // Current if sharpen
3025 case 2: proc->changeVF("sharpen", false); break;
3026 }
3027 // New filter
3028 mset.current_unsharp = id;
3029 switch (mset.current_unsharp) {
3030 case 1: proc->changeVF("blur", true); break;
3031 case 2: proc->changeVF("sharpen", true); break;
3032 }
3033 }
3034 }
3035}
3036
3037void Core::changeUpscale(bool b) {
3038 qDebug( "Core::changeUpscale: %d", b );
3039 if (mset.upscaling_filter != b) {
3040 mset.upscaling_filter = b;
3041 int width = DesktopInfo::desktop_size(mplayerwindow).width();
3042 CHANGE_VF("scale", b, QString::number(width) + ":-2");
3043 }
3044}
3045
3046void Core::changeStereo3d(const QString & in, const QString & out) {
3047 qDebug("Core::changeStereo3d: in: %s out: %s", in.toUtf8().constData(), out.toUtf8().constData());
3048
3049 if ((mset.stereo3d_in != in) || (mset.stereo3d_out != out)) {
3050 if (proc->isMPlayer()) {
3051 mset.stereo3d_in = in;
3052 mset.stereo3d_out = out;
3053 restartPlay();
3054 } else {
3055 // Remove previous filter
3056 if (mset.stereo3d_in != "none" && !mset.stereo3d_out.isEmpty()) {
3057 proc->changeStereo3DFilter(false, mset.stereo3d_in, mset.stereo3d_out);
3058 }
3059
3060 // New filter
3061 mset.stereo3d_in = in;
3062 mset.stereo3d_out = out;
3063 if (mset.stereo3d_in != "none" && !mset.stereo3d_out.isEmpty()) {
3064 proc->changeStereo3DFilter(true, mset.stereo3d_in, mset.stereo3d_out);
3065 }
3066 }
3067 }
3068}
3069
3070void Core::setBrightness(int value) {
3071 qDebug("Core::setBrightness: %d", value);
3072
3073 if (value > 100) value = 100;
3074 if (value < -100) value = -100;
3075
3076 if (value != mset.brightness) {
3077 proc->setPausingPrefix(pausing_prefix());
3078 proc->setBrightness(value);
3079 mset.brightness = value;
3080 displayMessage( tr("Brightness: %1").arg(value) );
3081 emit videoEqualizerNeedsUpdate();
3082 }
3083}
3084
3085
3086void Core::setContrast(int value) {
3087 qDebug("Core::setContrast: %d", value);
3088
3089 if (value > 100) value = 100;
3090 if (value < -100) value = -100;
3091
3092 if (value != mset.contrast) {
3093 proc->setPausingPrefix(pausing_prefix());
3094 proc->setContrast(value);
3095 mset.contrast = value;
3096 displayMessage( tr("Contrast: %1").arg(value) );
3097 emit videoEqualizerNeedsUpdate();
3098 }
3099}
3100
3101void Core::setGamma(int value) {
3102 qDebug("Core::setGamma: %d", value);
3103
3104 if (value > 100) value = 100;
3105 if (value < -100) value = -100;
3106
3107 if (value != mset.gamma) {
3108 proc->setPausingPrefix(pausing_prefix());
3109 proc->setGamma(value);
3110 mset.gamma= value;
3111 displayMessage( tr("Gamma: %1").arg(value) );
3112 emit videoEqualizerNeedsUpdate();
3113 }
3114}
3115
3116void Core::setHue(int value) {
3117 qDebug("Core::setHue: %d", value);
3118
3119 if (value > 100) value = 100;
3120 if (value < -100) value = -100;
3121
3122 if (value != mset.hue) {
3123 proc->setPausingPrefix(pausing_prefix());
3124 proc->setHue(value);
3125 mset.hue = value;
3126 displayMessage( tr("Hue: %1").arg(value) );
3127 emit videoEqualizerNeedsUpdate();
3128 }
3129}
3130
3131void Core::setSaturation(int value) {
3132 qDebug("Core::setSaturation: %d", value);
3133
3134 if (value > 100) value = 100;
3135 if (value < -100) value = -100;
3136
3137 if (value != mset.saturation) {
3138 proc->setPausingPrefix(pausing_prefix());
3139 proc->setSaturation(value);
3140 mset.saturation = value;
3141 displayMessage( tr("Saturation: %1").arg(value) );
3142 emit videoEqualizerNeedsUpdate();
3143 }
3144}
3145
3146void Core::incBrightness() {
3147 setBrightness(mset.brightness + pref->min_step);
3148}
3149
3150void Core::decBrightness() {
3151 setBrightness(mset.brightness - pref->min_step);
3152}
3153
3154void Core::incContrast() {
3155 setContrast(mset.contrast + pref->min_step);
3156}
3157
3158void Core::decContrast() {
3159 setContrast(mset.contrast - pref->min_step);
3160}
3161
3162void Core::incGamma() {
3163 setGamma(mset.gamma + pref->min_step);
3164}
3165
3166void Core::decGamma() {
3167 setGamma(mset.gamma - pref->min_step);
3168}
3169
3170void Core::incHue() {
3171 setHue(mset.hue + pref->min_step);
3172}
3173
3174void Core::decHue() {
3175 setHue(mset.hue - pref->min_step);
3176}
3177
3178void Core::incSaturation() {
3179 setSaturation(mset.saturation + pref->min_step);
3180}
3181
3182void Core::decSaturation() {
3183 setSaturation(mset.saturation - pref->min_step);
3184}
3185
3186void Core::setSpeed( double value ) {
3187 qDebug("Core::setSpeed: %f", value);
3188
3189 if (value < 0.10) value = 0.10;
3190 if (value > 100) value = 100;
3191
3192 mset.speed = value;
3193 proc->setSpeed(value);
3194
3195 displayMessage( tr("Speed: %1").arg(value) );
3196}
3197
3198void Core::incSpeed10() {
3199 qDebug("Core::incSpeed10");
3200 setSpeed( (double) mset.speed + 0.1 );
3201}
3202
3203void Core::decSpeed10() {
3204 qDebug("Core::decSpeed10");
3205 setSpeed( (double) mset.speed - 0.1 );
3206}
3207
3208void Core::incSpeed4() {
3209 qDebug("Core::incSpeed4");
3210 setSpeed( (double) mset.speed + 0.04 );
3211}
3212
3213void Core::decSpeed4() {
3214 qDebug("Core::decSpeed4");
3215 setSpeed( (double) mset.speed - 0.04 );
3216}
3217
3218void Core::incSpeed1() {
3219 qDebug("Core::incSpeed1");
3220 setSpeed( (double) mset.speed + 0.01 );
3221}
3222
3223void Core::decSpeed1() {
3224 qDebug("Core::decSpeed1");
3225 setSpeed( (double) mset.speed - 0.01 );
3226}
3227
3228void Core::doubleSpeed() {
3229 qDebug("Core::doubleSpeed");
3230 setSpeed( (double) mset.speed * 2 );
3231}
3232
3233void Core::halveSpeed() {
3234 qDebug("Core::halveSpeed");
3235 setSpeed( (double) mset.speed / 2 );
3236}
3237
3238void Core::normalSpeed() {
3239 setSpeed(1);
3240}
3241
3242int Core::adjustVolume(int v, int max_vol) {
3243 //qDebug() << "Core::adjustVolume: v:" << v << "max_vol:" << max_vol;
3244 if (max_vol < 100) max_vol = 100;
3245 int vol = v * max_vol / 100;
3246 return vol;
3247}
3248
3249void Core::setVolume(int volume, bool force) {
3250 qDebug("Core::setVolume: %d", volume);
3251
3252 int current_volume = (pref->global_volume ? pref->volume : mset.volume);
3253
3254 if ((volume == current_volume) && (!force)) return;
3255
3256 current_volume = volume;
3257 if (current_volume > 100) current_volume = 100;
3258 if (current_volume < 0) current_volume = 0;
3259
3260 if (proc->isMPV()) {
3261 // MPV
3262 int vol = adjustVolume(current_volume, pref->use_soft_vol ? pref->softvol_max : 100);
3263 proc->setVolume(vol);
3264 } else {
3265 // MPlayer
3266 if (state() == Paused) {
3267 // Change volume later, after quiting pause
3268 change_volume_after_unpause = true;
3269 } else {
3270 proc->setVolume(current_volume);
3271 }
3272 }
3273
3274 if (pref->global_volume) {
3275 pref->volume = current_volume;
3276 pref->mute = false;
3277 } else {
3278 mset.volume = current_volume;
3279 mset.mute = false;
3280 }
3281
3282 updateWidgets();
3283
3284 displayMessage( tr("Volume: %1").arg(current_volume) );
3285 emit volumeChanged( current_volume );
3286}
3287
3288void Core::switchMute() {
3289 qDebug("Core::switchMute");
3290
3291 mset.mute = !mset.mute;
3292 mute(mset.mute);
3293}
3294
3295void Core::mute(bool b) {
3296 qDebug("Core::mute");
3297
3298 proc->setPausingPrefix(pausing_prefix());
3299 proc->mute(b);
3300
3301 if (pref->global_volume) {
3302 pref->mute = b;
3303 } else {
3304 mset.mute = b;
3305 }
3306
3307 updateWidgets();
3308}
3309
3310void Core::incVolume(int step) {
3311 //qDebug("Core::incVolume");
3312 int vol = pref->global_volume ? pref->volume : mset.volume;
3313 setVolume(vol + step);
3314}
3315
3316void Core::decVolume(int step) {
3317 //qDebug("Core::incVolume");
3318 int vol = pref->global_volume ? pref->volume : mset.volume;
3319 setVolume(vol - step);
3320}
3321
3322void Core::incVolume() {
3323 qDebug("Core::incVolume");
3324 incVolume(pref->min_step);
3325}
3326
3327void Core::decVolume() {
3328 qDebug("Core::incVolume");
3329 decVolume(pref->min_step);
3330}
3331
3332void Core::setSubDelay(int delay) {
3333 qDebug("Core::setSubDelay: %d", delay);
3334 mset.sub_delay = delay;
3335 proc->setPausingPrefix(pausing_prefix());
3336 proc->setSubDelay((double) mset.sub_delay/1000);
3337 displayMessage( tr("Subtitle delay: %1 ms").arg(delay) );
3338}
3339
3340void Core::incSubDelay() {
3341 qDebug("Core::incSubDelay");
3342 setSubDelay(mset.sub_delay + 100);
3343}
3344
3345void Core::decSubDelay() {
3346 qDebug("Core::decSubDelay");
3347 setSubDelay(mset.sub_delay - 100);
3348}
3349
3350void Core::setAudioDelay(int delay) {
3351 qDebug("Core::setAudioDelay: %d", delay);
3352 mset.audio_delay = delay;
3353 proc->setPausingPrefix(pausing_prefix());
3354 proc->setAudioDelay((double) mset.audio_delay/1000);
3355 displayMessage( tr("Audio delay: %1 ms").arg(delay) );
3356}
3357
3358void Core::incAudioDelay() {
3359 qDebug("Core::incAudioDelay");
3360 setAudioDelay(mset.audio_delay + 100);
3361}
3362
3363void Core::decAudioDelay() {
3364 qDebug("Core::decAudioDelay");
3365 setAudioDelay(mset.audio_delay - 100);
3366}
3367
3368void Core::incSubPos() {
3369 qDebug("Core::incSubPos");
3370
3371 mset.sub_pos++;
3372 if (mset.sub_pos > 100) mset.sub_pos = 100;
3373 proc->setSubPos(mset.sub_pos);
3374}
3375
3376void Core::decSubPos() {
3377 qDebug("Core::decSubPos");
3378
3379 mset.sub_pos--;
3380 if (mset.sub_pos < 0) mset.sub_pos = 0;
3381 proc->setSubPos(mset.sub_pos);
3382}
3383
3384bool Core::subscale_need_restart() {
3385 bool need_restart = false;
3386
3387 need_restart = (pref->change_sub_scale_should_restart == Preferences::Enabled);
3388 if (pref->change_sub_scale_should_restart == Preferences::Detect) {
3389 if (pref->use_ass_subtitles)
3390 need_restart = (!MplayerVersion::isMplayerAtLeast(25843));
3391 else
3392 need_restart = (!MplayerVersion::isMplayerAtLeast(23745));
3393 }
3394 return need_restart;
3395}
3396
3397void Core::changeSubScale(double value) {
3398 qDebug("Core::changeSubScale: %f", value);
3399
3400 bool need_restart = subscale_need_restart();
3401
3402 if (value < 0) value = 0;
3403
3404 if (pref->use_ass_subtitles) {
3405 if (value != mset.sub_scale_ass) {
3406 mset.sub_scale_ass = value;
3407 if (need_restart) {
3408 restartPlay();
3409 } else {
3410 proc->setSubScale(mset.sub_scale_ass);
3411 }
3412 displayMessage( tr("Font scale: %1").arg(mset.sub_scale_ass) );
3413 }
3414 } else {
3415 // No ass
3416 if (value != mset.sub_scale) {
3417 mset.sub_scale = value;
3418 if (need_restart) {
3419 restartPlay();
3420 } else {
3421 proc->setSubScale(mset.sub_scale);
3422 }
3423 displayMessage( tr("Font scale: %1").arg(mset.sub_scale) );
3424 }
3425 }
3426}
3427
3428void Core::incSubScale() {
3429 double step = 0.20;
3430
3431 if (pref->use_ass_subtitles) {
3432 changeSubScale( mset.sub_scale_ass + step );
3433 } else {
3434 if (subscale_need_restart()) step = 1;
3435 changeSubScale( mset.sub_scale + step );
3436 }
3437}
3438
3439void Core::decSubScale() {
3440 double step = 0.20;
3441
3442 if (pref->use_ass_subtitles) {
3443 changeSubScale( mset.sub_scale_ass - step );
3444 } else {
3445 if (subscale_need_restart()) step = 1;
3446 changeSubScale( mset.sub_scale - step );
3447 }
3448}
3449
3450void Core::changeOSDScale(double value) {
3451 qDebug("Core::changeOSDScale: %f", value);
3452
3453 if (value < 0) value = 0;
3454
3455 if (proc->isMPlayer()) {
3456 if (value != pref->subfont_osd_scale) {
3457 pref->subfont_osd_scale = value;
3458 restartPlay();
3459 }
3460 } else {
3461 if (value != pref->osd_scale) {
3462 pref->osd_scale = value;
3463 proc->setOSDScale(pref->osd_scale);
3464 }
3465 }
3466}
3467
3468void Core::incOSDScale() {
3469 if (proc->isMPlayer()) {
3470 changeOSDScale(pref->subfont_osd_scale + 1);
3471 } else {
3472 changeOSDScale(pref->osd_scale + 0.20);
3473 }
3474}
3475
3476void Core::decOSDScale() {
3477 if (proc->isMPlayer()) {
3478 changeOSDScale(pref->subfont_osd_scale - 1);
3479 } else {
3480 changeOSDScale(pref->osd_scale - 0.20);
3481 }
3482}
3483
3484void Core::incSubStep() {
3485 qDebug("Core::incSubStep");
3486 proc->setSubStep(+1);
3487}
3488
3489void Core::decSubStep() {
3490 qDebug("Core::decSubStep");
3491 proc->setSubStep(-1);
3492}
3493
3494void Core::changeSubVisibility(bool visible) {
3495 qDebug("Core::changeSubVisilibity: %d", visible);
3496 pref->sub_visibility = visible;
3497 proc->setSubtitlesVisibility(pref->sub_visibility);
3498
3499 if (pref->sub_visibility)
3500 displayMessage( tr("Subtitles on") );
3501 else
3502 displayMessage( tr("Subtitles off") );
3503}
3504
3505void Core::changeExternalSubFPS(int fps_id) {
3506 qDebug("Core::setExternalSubFPS: %d", fps_id);
3507 mset.external_subtitles_fps = fps_id;
3508 if (!mset.external_subtitles.isEmpty()) {
3509 restartPlay();
3510 }
3511}
3512
3513// Audio equalizer functions
3514void Core::setAudioEqualizer(AudioEqualizerList values, bool restart) {
3515 qDebug("Core::setAudioEqualizer");
3516
3517 if (pref->global_audio_equalizer) {
3518 pref->audio_equalizer = values;
3519 } else {
3520 mset.audio_equalizer = values;
3521 }
3522
3523 if (!pref->use_audio_equalizer) {
3524 qDebug("Core::setAudioEqualizer: the audio equalizer is disabled. Ignoring.");
3525 return;
3526 }
3527
3528 if (!restart) {
3529 proc->setAudioEqualizer(Helper::equalizerListToString(values));
3530 } else {
3531 restartPlay();
3532 }
3533
3534 // Infinite recursion
3535 //emit audioEqualizerNeedsUpdate();
3536}
3537
3538void Core::updateAudioEqualizer() {
3539 setAudioEqualizer(pref->global_audio_equalizer ? pref->audio_equalizer : mset.audio_equalizer);
3540}
3541
3542void Core::setAudioEq(int eq, int value) {
3543 if (pref->global_audio_equalizer) {
3544 pref->audio_equalizer[eq] = value;
3545 } else {
3546 mset.audio_equalizer[eq] = value;
3547 }
3548 updateAudioEqualizer();
3549}
3550
3551void Core::setAudioEq0(int value) {
3552 setAudioEq(0, value);
3553}
3554
3555void Core::setAudioEq1(int value) {
3556 setAudioEq(1, value);
3557}
3558
3559void Core::setAudioEq2(int value) {
3560 setAudioEq(2, value);
3561}
3562
3563void Core::setAudioEq3(int value) {
3564 setAudioEq(3, value);
3565}
3566
3567void Core::setAudioEq4(int value) {
3568 setAudioEq(4, value);
3569}
3570
3571void Core::setAudioEq5(int value) {
3572 setAudioEq(5, value);
3573}
3574
3575void Core::setAudioEq6(int value) {
3576 setAudioEq(6, value);
3577}
3578
3579void Core::setAudioEq7(int value) {
3580 setAudioEq(7, value);
3581}
3582
3583void Core::setAudioEq8(int value) {
3584 setAudioEq(8, value);
3585}
3586
3587void Core::setAudioEq9(int value) {
3588 setAudioEq(9, value);
3589}
3590
3591
3592
3593void Core::changeCurrentSec(double sec) {
3594 //qDebug() << "Core::changeCurrentSec:" << sec << "starting_time:" << mset.starting_time;
3595
3596 mset.current_sec = sec;
3597
3598#ifdef MSET_USE_STARTING_TIME
3599 if (mset.starting_time != -1) {
3600 mset.current_sec -= mset.starting_time;
3601
3602 // handle PTS rollover at MPEG-TS
3603 if (mset.current_sec < 0 && mset.current_demuxer == "mpegts") {
3604 mset.current_sec += 8589934592.0 / 90000.0; // 2^33 / 90 kHz
3605 }
3606 }
3607#endif
3608
3609 if (state() != Playing) {
3610 setState(Playing);
3611 qDebug("Core::changeCurrentSec: mplayer reports that now it's playing");
3612 //emit mediaStartPlay();
3613 //emit stateChanged(state());
3614 }
3615
3616 emit showTime(mset.current_sec);
3617
3618 // Emit posChanged:
3619 static int last_second = 0;
3620
3621 if (floor(sec)==last_second) return; // Update only once per second
3622 last_second = (int) floor(sec);
3623
3624#ifdef SEEKBAR_RESOLUTION
3625 int value = 0;
3626 if ( (mdat.duration > 1) && (mset.current_sec > 1) &&
3627 (mdat.duration > mset.current_sec) )
3628 {
3629 value = ( (int) mset.current_sec * SEEKBAR_RESOLUTION) / (int) mdat.duration;
3630 }
3631 emit positionChanged(value);
3632#else
3633 int perc = 0;
3634 if ( (mdat.duration > 1) && (mset.current_sec > 1) &&
3635 (mdat.duration > mset.current_sec) )
3636 {
3637 perc = ( (int) mset.current_sec * 100) / (int) mdat.duration;
3638 }
3639 emit posChanged( perc );
3640#endif
3641}
3642
3643void Core::gotStartingTime(double time) {
3644 qDebug("Core::gotStartingTime: %f", time);
3645 qDebug("Core::gotStartingTime: current_sec: %f", mset.current_sec);
3646
3647#ifdef MSET_USE_STARTING_TIME
3648 if ((mset.starting_time == -1.0) && (mset.current_sec == 0)) {
3649 mset.starting_time = time;
3650 qDebug("Core::gotStartingTime: starting time set to %f", time);
3651 }
3652#endif
3653}
3654
3655void Core::gotVideoBitrate(int b) {
3656 qDebug("Core::gotVideoBitrate: %d", b);
3657 mdat.video_bitrate = b;
3658 emit bitrateChanged(mdat.video_bitrate, mdat.audio_bitrate);
3659}
3660
3661void Core::gotAudioBitrate(int b) {
3662 qDebug("Core::gotAudioBitrate: %d", b);
3663 mdat.audio_bitrate = b;
3664 emit bitrateChanged(mdat.video_bitrate, mdat.audio_bitrate);
3665}
3666
3667void Core::changePause() {
3668 qDebug("Core::changePause");
3669 qDebug("Core::changePause: mplayer reports that it's paused");
3670 setState(Paused);
3671 //emit stateChanged(state());
3672}
3673
3674void Core::changeDeinterlace(int ID) {
3675 qDebug("Core::changeDeinterlace: %d", ID);
3676
3677 if (ID != mset.current_deinterlacer) {
3678 if (proc->isMPlayer()) {
3679 mset.current_deinterlacer = ID;
3680 restartPlay();
3681 } else {
3682 // MPV
3683 // Remove previous filter
3684 switch (mset.current_deinterlacer) {
3685 case MediaSettings::L5: proc->changeVF("l5", false); break;
3686 case MediaSettings::Yadif: proc->changeVF("yadif", false); break;
3687 case MediaSettings::LB: proc->changeVF("lb", false); break;
3688 case MediaSettings::Yadif_1: proc->changeVF("yadif", false, "1"); break;
3689 case MediaSettings::Kerndeint: proc->changeVF("kerndeint", false, "5"); break;
3690 }
3691 mset.current_deinterlacer = ID;
3692 // New filter
3693 switch (mset.current_deinterlacer) {
3694 case MediaSettings::L5: proc->changeVF("l5", true); break;
3695 case MediaSettings::Yadif: proc->changeVF("yadif", true); break;
3696 case MediaSettings::LB: proc->changeVF("lb", true); break;
3697 case MediaSettings::Yadif_1: proc->changeVF("yadif", true, "1"); break;
3698 case MediaSettings::Kerndeint: proc->changeVF("kerndeint", true, "5"); break;
3699 }
3700 }
3701 }
3702}
3703
3704
3705
3706void Core::changeSubtitle(int ID) {
3707 qDebug("Core::changeSubtitle: %d", ID);
3708
3709 mset.current_sub_id = ID;
3710 if (ID==MediaSettings::SubNone) {
3711 ID=-1;
3712 }
3713
3714 if (ID==MediaSettings::NoneSelected) {
3715 ID=-1;
3716 qDebug("Core::changeSubtitle: subtitle is NoneSelected, this shouldn't happen. ID set to -1.");
3717 }
3718
3719 qDebug("Core::changeSubtitle: ID: %d", ID);
3720
3721 int real_id = -1;
3722 if (ID == -1) {
3723 proc->disableSubtitles();
3724 } else {
3725 bool valid_item = ( (ID >= 0) && (ID < mdat.subs.numItems()) );
3726 if (!valid_item) qWarning("Core::changeSubtitle: ID: %d is not valid!", ID);
3727 if ( (mdat.subs.numItems() > 0) && (valid_item) ) {
3728 real_id = mdat.subs.itemAt(ID).ID();
3729 proc->setSubtitle(mdat.subs.itemAt(ID).type(), real_id);
3730 } else {
3731 qWarning("Core::changeSubtitle: subtitle list is empty!");
3732 }
3733 }
3734
3735 updateWidgets();
3736}
3737
3738void Core::nextSubtitle() {
3739 qDebug("Core::nextSubtitle");
3740
3741 if ( (mset.current_sub_id == MediaSettings::SubNone) &&
3742 (mdat.subs.numItems() > 0) )
3743 {
3744 changeSubtitle(0);
3745 }
3746 else {
3747 int item = mset.current_sub_id + 1;
3748 if (item >= mdat.subs.numItems()) {
3749 item = MediaSettings::SubNone;
3750 }
3751 changeSubtitle( item );
3752 }
3753}
3754
3755#ifdef MPV_SUPPORT
3756void Core::changeSecondarySubtitle(int ID) {
3757 // MPV only
3758 qDebug("Core::changeSecondarySubtitle: %d", ID);
3759
3760 mset.current_secondary_sub_id = ID;
3761 if (ID == MediaSettings::SubNone) {
3762 ID = -1;
3763 }
3764 if (ID == MediaSettings::NoneSelected) {
3765 ID = -1;
3766 }
3767
3768 if (ID == -1) {
3769 proc->disableSecondarySubtitles();
3770 } else {
3771 int real_id = -1;
3772 bool valid_item = ( (ID >= 0) && (ID < mdat.subs.numItems()) );
3773 if (!valid_item) qWarning("Core::changeSecondarySubtitle: ID: %d is not valid!", ID);
3774 if ( (mdat.subs.numItems() > 0) && (valid_item) ) {
3775 real_id = mdat.subs.itemAt(ID).ID();
3776 proc->setSecondarySubtitle(real_id);
3777 }
3778 }
3779}
3780#endif
3781
3782void Core::changeAudio(int ID, bool allow_restart) {
3783 qDebug("Core::changeAudio: ID: %d, allow_restart: %d", ID, allow_restart);
3784
3785 if (ID!=mset.current_audio_id) {
3786 mset.current_audio_id = ID;
3787 qDebug("changeAudio: ID: %d", ID);
3788
3789 bool need_restart = false;
3790 #ifdef OBSOLETE_FAST_AUDIO_CHANGE
3791 if (allow_restart) {
3792 need_restart = (pref->fast_audio_change == Preferences::Disabled);
3793 if (pref->fast_audio_change == Preferences::Detect) {
3794 need_restart = (!MplayerVersion::isMplayerAtLeast(21441));
3795 }
3796 }
3797 #endif
3798
3799 if (need_restart) {
3800 restartPlay();
3801 } else {
3802 proc->setAudio(ID);
3803 // Workaround for a mplayer problem in windows,
3804 // volume is too loud after changing audio.
3805
3806 // Workaround too for a mplayer problem in linux,
3807 // the volume is reduced if using -softvol-max.
3808
3809 if (proc->isMPlayer()) {
3810 if (pref->mplayer_additional_options.contains("-volume")) {
3811 qDebug("Core::changeAudio: don't set volume since -volume is used");
3812 } else {
3813 if (pref->global_volume) {
3814 setVolume( pref->volume, true);
3815 if (pref->mute) mute(true);
3816 } else {
3817 setVolume( mset.volume, true );
3818 if (mset.mute) mute(true); // if muted, mute again
3819 }
3820 }
3821 }
3822 updateWidgets();
3823 }
3824 }
3825}
3826
3827void Core::nextAudio() {
3828 qDebug("Core::nextAudio");
3829
3830 int item = mdat.audios.find( mset.current_audio_id );
3831 if (item == -1) {
3832 qWarning("Core::nextAudio: audio ID %d not found!", mset.current_audio_id);
3833 } else {
3834 qDebug( "Core::nextAudio: numItems: %d, item: %d", mdat.audios.numItems(), item);
3835 item++;
3836 if (item >= mdat.audios.numItems()) item=0;
3837 int ID = mdat.audios.itemAt(item).ID();
3838 qDebug( "Core::nextAudio: item: %d, ID: %d", item, ID);
3839 changeAudio( ID );
3840 }
3841}
3842
3843void Core::changeVideo(int ID, bool allow_restart) {
3844 qDebug("Core::changeVideo: ID: %d, allow_restart: %d", ID, allow_restart);
3845
3846 if (ID != mset.current_video_id) {
3847 mset.current_video_id = ID;
3848 qDebug("Core::changeVideo: ID set to: %d", ID);
3849
3850 bool need_restart = false;
3851 if (allow_restart) {
3852 // afaik lavf doesn't require to restart, any other?
3853 need_restart = ((mdat.demuxer != "lavf") && (mdat.demuxer != "mpegts"));
3854 }
3855
3856 if (need_restart) {
3857 restartPlay();
3858 } else {
3859 if (mdat.demuxer == "nsv") {
3860 // Workaround a problem with the nsv demuxer
3861 qWarning("Core::changeVideo: not changing the video with nsv to prevent mplayer go crazy");
3862 } else {
3863 proc->setVideo(ID);
3864 }
3865 }
3866 }
3867}
3868
3869void Core::nextVideo() {
3870 qDebug("Core::nextVideo");
3871
3872 int item = mdat.videos.find( mset.current_video_id );
3873 if (item == -1) {
3874 qWarning("Core::nextVideo: video ID %d not found!", mset.current_video_id);
3875 } else {
3876 qDebug( "Core::nextVideo: numItems: %d, item: %d", mdat.videos.numItems(), item);
3877 item++;
3878 if (item >= mdat.videos.numItems()) item=0;
3879 int ID = mdat.videos.itemAt(item).ID();
3880 qDebug( "Core::nextVideo: item: %d, ID: %d", item, ID);
3881 changeVideo( ID );
3882 }
3883}
3884
3885#if PROGRAM_SWITCH
3886void Core::changeProgram(int ID) {
3887 qDebug("Core::changeProgram: %d", ID);
3888
3889 if (ID != mset.current_program_id) {
3890 mset.current_program_id = ID;
3891 proc->setTSProgram(ID);
3892
3893 /*
3894 mset.current_video_id = MediaSettings::NoneSelected;
3895 mset.current_audio_id = MediaSettings::NoneSelected;
3896
3897 updateWidgets();
3898 */
3899 }
3900}
3901
3902void Core::nextProgram() {
3903 qDebug("Core::nextProgram");
3904 // Not implemented yet
3905}
3906
3907#endif
3908
3909void Core::changeTitle(int ID) {
3910 if (mdat.type == TYPE_VCD) {
3911 // VCD
3912 openVCD( ID );
3913 }
3914 else
3915 if (mdat.type == TYPE_AUDIO_CD) {
3916 // AUDIO CD
3917 openAudioCD( ID );
3918 }
3919 else
3920 if (mdat.type == TYPE_DVD) {
3921 #if DVDNAV_SUPPORT
3922 if (mdat.filename.startsWith("dvdnav:")) {
3923 proc->setTitle(ID);
3924 } else {
3925 #endif
3926 DiscData disc_data = DiscName::split(mdat.filename);
3927 disc_data.title = ID;
3928 QString dvd_url = DiscName::join(disc_data);
3929
3930 openDVD( DiscName::join(disc_data) );
3931 #if DVDNAV_SUPPORT
3932 }
3933 #endif
3934 }
3935#ifdef BLURAY_SUPPORT
3936 else
3937 if (mdat.type == TYPE_BLURAY) {
3938 //DiscName::test();
3939
3940 DiscData disc_data = DiscName::split(mdat.filename);
3941 disc_data.title = ID;
3942 QString bluray_url = DiscName::join(disc_data);
3943 qDebug("Core::changeTitle: bluray_url: %s", bluray_url.toUtf8().constData());
3944 openBluRay(bluray_url);
3945 }
3946#endif
3947}
3948
3949void Core::changeChapter(int ID) {
3950 qDebug("Core::changeChapter: ID: %d", ID);
3951 proc->setChapter(ID);
3952}
3953
3954int Core::firstChapter() {
3955 if ( (MplayerVersion::isMplayerAtLeast(25391)) &&
3956 (!MplayerVersion::isMplayerAtLeast(29407)) )
3957 return 1;
3958 else
3959 return 0;
3960}
3961
3962int Core::firstDVDTitle() {
3963 if (proc->isMPV()) {
3964 return 0;
3965 } else {
3966 return 1;
3967 }
3968}
3969
3970int Core::firstBlurayTitle() {
3971 if (proc->isMPV()) {
3972 return 0;
3973 } else {
3974 return 1;
3975 }
3976}
3977
3978void Core::prevChapter() {
3979 qDebug("Core::prevChapter");
3980 proc->previousChapter();
3981}
3982
3983void Core::nextChapter() {
3984 qDebug("Core::nextChapter");
3985 proc->nextChapter();
3986}
3987
3988void Core::changeAngle(int ID) {
3989 qDebug("Core::changeAngle: ID: %d", ID);
3990
3991 if (ID != mset.current_angle_id) {
3992 mset.current_angle_id = ID;
3993 restartPlay();
3994 }
3995}
3996
3997void Core::changeAspectRatio( int ID ) {
3998 qDebug("Core::changeAspectRatio: %d", ID);
3999
4000 mset.aspect_ratio_id = ID;
4001
4002 double asp = mset.aspectToNum( (MediaSettings::Aspect) ID);
4003
4004 if (!pref->use_mplayer_window) {
4005 mplayerwindow->setAspect(asp);
4006 } else {
4007 // Using mplayer own window
4008 if (!mdat.novideo) {
4009 if (ID == MediaSettings::AspectAuto) {
4010 asp = mdat.video_aspect;
4011 }
4012 proc->setAspect(asp);
4013 }
4014 }
4015
4016 QString asp_name = MediaSettings::aspectToString( (MediaSettings::Aspect) mset.aspect_ratio_id);
4017 displayMessage( tr("Aspect ratio: %1").arg(asp_name) );
4018}
4019
4020void Core::nextAspectRatio() {
4021 // Ordered list
4022 QList<int> s;
4023 s << MediaSettings::AspectNone
4024 << MediaSettings::AspectAuto
4025 << MediaSettings::Aspect11 // 1
4026 << MediaSettings::Aspect54 // 1.25
4027 << MediaSettings::Aspect43 // 1.33
4028 << MediaSettings::Aspect118 // 1.37
4029 << MediaSettings::Aspect1410 // 1.4
4030 << MediaSettings::Aspect32 // 1.5
4031 << MediaSettings::Aspect149 // 1.55
4032 << MediaSettings::Aspect1610 // 1.6
4033 << MediaSettings::Aspect169 // 1.77
4034 << MediaSettings::Aspect235; // 2.35
4035
4036 int i = s.indexOf( mset.aspect_ratio_id ) + 1;
4037 if (i >= s.count()) i = 0;
4038
4039 int new_aspect_id = s[i];
4040
4041 changeAspectRatio( new_aspect_id );
4042 updateWidgets();
4043}
4044
4045void Core::nextWheelFunction() {
4046 int a = pref->wheel_function;
4047
4048 bool done = false;
4049 if(((int ) pref->wheel_function_cycle)==0)
4050 return;
4051 while(!done){
4052 // get next a
4053
4054 a = a*2;
4055 if(a==32)
4056 a = 2;
4057 // See if we are done
4058 if (pref->wheel_function_cycle.testFlag((Preferences::WheelFunction)a))
4059 done = true;
4060 }
4061 pref->wheel_function = a;
4062 QString m = "";
4063 switch(a){
4064 case Preferences::Seeking:
4065 m = tr("Mouse wheel seeks now");
4066 break;
4067 case Preferences::Volume:
4068 m = tr("Mouse wheel changes volume now");
4069 break;
4070 case Preferences::Zoom:
4071 m = tr("Mouse wheel changes zoom level now");
4072 break;
4073 case Preferences::ChangeSpeed:
4074 m = tr("Mouse wheel changes speed now");
4075 break;
4076 }
4077 displayMessage(m);
4078}
4079
4080void Core::changeLetterbox(bool b) {
4081 qDebug("Core::changeLetterbox: %d", b);
4082
4083 if (mset.add_letterbox != b) {
4084 mset.add_letterbox = b;
4085 CHANGE_VF("letterbox", b, DesktopInfo::desktop_aspectRatio(mplayerwindow));
4086 }
4087}
4088
4089#ifdef ADD_BLACKBORDERS_FS
4090void Core::changeLetterboxOnFullscreen(bool b) {
4091 qDebug("Core::changeLetterboxOnFullscreen: %d", b);
4092 CHANGE_VF("letterbox", b, DesktopInfo::desktop_aspectRatio(mplayerwindow));
4093}
4094#endif
4095
4096void Core::changeOSD(int v) {
4097 qDebug("Core::changeOSD: %d", v);
4098
4099 pref->osd = v;
4100
4101 proc->setPausingPrefix(pausing_prefix());
4102 proc->setOSD(pref->osd);
4103
4104 updateWidgets();
4105}
4106
4107void Core::nextOSD() {
4108 int osd = pref->osd + 1;
4109 if (osd > Preferences::SeekTimerTotal) {
4110 osd = Preferences::None;
4111 }
4112 changeOSD( osd );
4113}
4114
4115void Core::changeRotate(int r) {
4116 qDebug("Core::changeRotate: %d", r);
4117
4118 if (mset.rotate != r) {
4119 if (proc->isMPlayer()) {
4120 mset.rotate = r;
4121 restartPlay();
4122 } else {
4123 // MPV
4124 // Remove previous filter
4125 switch (mset.rotate) {
4126 case MediaSettings::Clockwise_flip: proc->changeVF("rotate", false, MediaSettings::Clockwise_flip); break;
4127 case MediaSettings::Clockwise: proc->changeVF("rotate", false, MediaSettings::Clockwise); break;
4128 case MediaSettings::Counterclockwise: proc->changeVF("rotate", false, MediaSettings::Counterclockwise); break;
4129 case MediaSettings::Counterclockwise_flip: proc->changeVF("rotate", false, MediaSettings::Counterclockwise_flip); break;
4130 }
4131 mset.rotate = r;
4132 // New filter
4133 switch (mset.rotate) {
4134 case MediaSettings::Clockwise_flip: proc->changeVF("rotate", true, MediaSettings::Clockwise_flip); break;
4135 case MediaSettings::Clockwise: proc->changeVF("rotate", true, MediaSettings::Clockwise); break;
4136 case MediaSettings::Counterclockwise: proc->changeVF("rotate", true, MediaSettings::Counterclockwise); break;
4137 case MediaSettings::Counterclockwise_flip: proc->changeVF("rotate", true, MediaSettings::Counterclockwise_flip); break;
4138 }
4139 }
4140 }
4141}
4142
4143#if USE_ADAPTER
4144void Core::changeAdapter(int n) {
4145 qDebug("Core::changeScreen: %d", n);
4146
4147 if (pref->adapter != n) {
4148 pref->adapter = n;
4149 restartPlay();
4150 }
4151}
4152#endif
4153
4154void Core::changeAO(const QString & new_ao) {
4155 qDebug() << "Core::changeAO:" << new_ao;
4156 if (pref->ao != new_ao) {
4157 pref->ao = new_ao;
4158 if (proc->isRunning()) restartPlay();
4159 }
4160}
4161
4162#if 0
4163void Core::changeSize(int n) {
4164 if ( /*(n != pref->size_factor) &&*/ (!pref->use_mplayer_window) ) {
4165 pref->size_factor = n;
4166
4167 emit needResize(mset.win_width, mset.win_height);
4168 updateWidgets();
4169 }
4170}
4171
4172void Core::toggleDoubleSize() {
4173 if (pref->size_factor != 100)
4174 changeSize(100);
4175 else
4176 changeSize(200);
4177}
4178#endif
4179
4180void Core::changeZoom(double p) {
4181 qDebug("Core::changeZoom: %f", p);
4182 if (p < ZOOM_MIN) p = ZOOM_MIN;
4183
4184 mset.zoom_factor = p;
4185 mplayerwindow->setZoom(p);
4186 displayMessage( tr("Zoom: %1").arg(mset.zoom_factor) );
4187}
4188
4189void Core::resetZoom() {
4190 changeZoom(1.0);
4191}
4192
4193void Core::autoZoom() {
4194 double video_aspect = mset.aspectToNum( (MediaSettings::Aspect) mset.aspect_ratio_id);
4195
4196 if (video_aspect <= 0) {
4197 QSize w = mplayerwindow->videoLayer()->size();
4198 video_aspect = (double) w.width() / w.height();
4199 }
4200
4201 double screen_aspect = DesktopInfo::desktop_aspectRatio(mplayerwindow);
4202 double zoom_factor;
4203
4204 if (video_aspect > screen_aspect)
4205 zoom_factor = video_aspect / screen_aspect;
4206 else
4207 zoom_factor = screen_aspect / video_aspect;
4208
4209 qDebug("Core::autoZoom: video_aspect: %f", video_aspect);
4210 qDebug("Core::autoZoom: screen_aspect: %f", screen_aspect);
4211 qDebug("Core::autoZoom: zoom_factor: %f", zoom_factor);
4212
4213 changeZoom(zoom_factor);
4214}
4215
4216void Core::autoZoomFromLetterbox(double aspect) {
4217 qDebug("Core::autoZoomFromLetterbox: %f", aspect);
4218
4219 // Probably there's a much easy way to do this, but I'm not good with maths...
4220
4221 QSize desktop = DesktopInfo::desktop_size(mplayerwindow);
4222
4223 double video_aspect = mset.aspectToNum( (MediaSettings::Aspect) mset.aspect_ratio_id);
4224
4225 if (video_aspect <= 0) {
4226 QSize w = mplayerwindow->videoLayer()->size();
4227 video_aspect = (double) w.width() / w.height();
4228 }
4229
4230 // Calculate size of the video in fullscreen
4231 QSize video;
4232 video.setHeight( desktop.height() );;
4233 video.setWidth( (int) (video.height() * video_aspect) );
4234 if (video.width() > desktop.width()) {
4235 video.setWidth( desktop.width() );;
4236 video.setHeight( (int) (video.width() / video_aspect) );
4237 }
4238
4239 qDebug("Core::autoZoomFromLetterbox: max. size of video: %d %d", video.width(), video.height());
4240
4241 // Calculate the size of the actual video inside the letterbox
4242 QSize actual_video;
4243 actual_video.setWidth( video.width() );
4244 actual_video.setHeight( (int) (actual_video.width() / aspect) );
4245
4246 qDebug("Core::autoZoomFromLetterbox: calculated size of actual video for aspect %f: %d %d", aspect, actual_video.width(), actual_video.height());
4247
4248 double zoom_factor = (double) desktop.height() / actual_video.height();
4249
4250 qDebug("Core::autoZoomFromLetterbox: calculated zoom factor: %f", zoom_factor);
4251 changeZoom(zoom_factor);
4252}
4253
4254void Core::autoZoomFor169() {
4255 autoZoomFromLetterbox((double) 16 / 9);
4256}
4257
4258void Core::autoZoomFor235() {
4259 autoZoomFromLetterbox(2.35);
4260}
4261
4262void Core::incZoom() {
4263 qDebug("Core::incZoom");
4264 changeZoom( mset.zoom_factor + ZOOM_STEP );
4265}
4266
4267void Core::decZoom() {
4268 qDebug("Core::decZoom");
4269 changeZoom( mset.zoom_factor - ZOOM_STEP );
4270}
4271
4272void Core::showFilenameOnOSD() {
4273#ifdef MPV_SUPPORT
4274 if (proc->isMPV()) proc->setOSDMediaInfo(pref->mpv_osd_media_info);
4275#endif
4276#ifdef MPLAYER_SUPPORT
4277 if (proc->isMPlayer()) proc->setOSDMediaInfo(pref->mplayer_osd_media_info);
4278#endif
4279
4280 proc->showFilenameOnOSD();
4281}
4282
4283void Core::showTimeOnOSD() {
4284 proc->showTimeOnOSD();
4285}
4286
4287void Core::toggleDeinterlace() {
4288 qDebug("Core::toggleDeinterlace");
4289 proc->toggleDeinterlace();
4290}
4291
4292void Core::changeUseCustomSubStyle(bool b) {
4293 qDebug("Core::changeUseCustomSubStyle: %d", b);
4294
4295 if (pref->enable_ass_styles != b) {
4296 pref->enable_ass_styles = b;
4297 if (proc->isRunning()) restartPlay();
4298 }
4299}
4300
4301void Core::toggleForcedSubsOnly(bool b) {
4302 qDebug("Core::toggleForcedSubsOnly: %d", b);
4303
4304 if (pref->use_forced_subs_only != b) {
4305 pref->use_forced_subs_only = b;
4306 //if (proc->isRunning()) restartPlay();
4307 proc->setSubForcedOnly(b);
4308 }
4309}
4310
4311void Core::changeClosedCaptionChannel(int c) {
4312 qDebug("Core::changeClosedCaptionChannel: %d", c);
4313 if (c != mset.closed_caption_channel) {
4314 mset.closed_caption_channel = c;
4315 if (proc->isRunning()) restartPlay();
4316 }
4317}
4318
4319/*
4320void Core::nextClosedCaptionChannel() {
4321 int c = mset.closed_caption_channel;
4322 c++;
4323 if (c > 4) c = 0;
4324 changeClosedCaptionChannel(c);
4325}
4326
4327void Core::prevClosedCaptionChannel() {
4328 int c = mset.closed_caption_channel;
4329 c--;
4330 if (c < 0) c = 4;
4331 changeClosedCaptionChannel(c);
4332}
4333*/
4334
4335#if DVDNAV_SUPPORT
4336// dvdnav buttons
4337void Core::dvdnavUp() {
4338 qDebug("Core::dvdnavUp");
4339 proc->discButtonPressed("up");
4340}
4341
4342void Core::dvdnavDown() {
4343 qDebug("Core::dvdnavDown");
4344 proc->discButtonPressed("down");
4345}
4346
4347void Core::dvdnavLeft() {
4348 qDebug("Core::dvdnavLeft");
4349 proc->discButtonPressed("left");
4350}
4351
4352void Core::dvdnavRight() {
4353 qDebug("Core::dvdnavRight");
4354 proc->discButtonPressed("right");
4355}
4356
4357void Core::dvdnavMenu() {
4358 qDebug("Core::dvdnavMenu");
4359 proc->discButtonPressed("menu");
4360}
4361
4362void Core::dvdnavSelect() {
4363 qDebug("Core::dvdnavSelect");
4364 proc->discButtonPressed("select");
4365}
4366
4367void Core::dvdnavPrev() {
4368 qDebug("Core::dvdnavPrev");
4369 proc->discButtonPressed("prev");
4370}
4371
4372void Core::dvdnavMouse() {
4373 qDebug("Core::dvdnavMouse");
4374
4375 if ((state() == Playing) && (mdat.filename.startsWith("dvdnav:"))) {
4376 proc->discButtonPressed("mouse");
4377 }
4378}
4379#endif
4380
4381void Core::displayMessage(QString text) {
4382 qDebug("Core::displayMessage");
4383 emit showMessage(text);
4384
4385 if ((pref->fullscreen) && (state() != Paused)) {
4386 displayTextOnOSD( text );
4387 }
4388}
4389
4390void Core::displayScreenshotName(QString filename) {
4391 qDebug("Core::displayScreenshotName: %s", filename.toUtf8().constData());
4392
4393 QFileInfo fi(filename);
4394
4395 QString text = tr("Screenshot saved as %1").arg(fi.fileName());
4396 //QString text = QString("Screenshot saved as %1").arg(fi.fileName());
4397
4398#ifdef MPLAYER2_SUPPORT
4399 if (MplayerVersion::isMplayer2()) {
4400 displayTextOnOSD(text, 3000, 1, "");
4401 }
4402 else
4403#endif
4404 if (MplayerVersion::isMplayerAtLeast(27665)) {
4405 displayTextOnOSD(text, 3000, 1, "pausing_keep_force");
4406 }
4407 else
4408 if (state() != Paused) {
4409 // Dont' show the message on OSD while in pause, otherwise
4410 // the video goes forward a frame.
4411 displayTextOnOSD(text, 3000, 1, "pausing_keep");
4412 }
4413
4414 emit showMessage(text);
4415}
4416
4417void Core::displayUpdatingFontCache() {
4418 qDebug("Core::displayUpdatingFontCache");
4419 emit showMessage( tr("Updating the font cache. This may take some seconds...") );
4420}
4421
4422void Core::displayBuffering() {
4423 setState(Buffering);
4424// emit showMessage(tr("Buffering..."));
4425}
4426
4427void Core::displayPlaying() {
4428 qDebug("Core::displayPlaying");
4429 setState(Buffering);
4430 emit showMessage(tr("Starting..."), 60000);
4431}
4432
4433void Core::gotWindowResolution(int w, int h) {
4434 qDebug("Core::gotWindowResolution: %d, %d", w, h);
4435 //double aspect = (double) w/h;
4436
4437 if (pref->use_mplayer_window) {
4438 emit noVideo();
4439 } else {
4440 if ((pref->resize_method==Preferences::Afterload) && (we_are_restarting)) {
4441 // Do nothing
4442 } else {
4443 emit needResize(w,h);
4444 }
4445 }
4446
4447 mset.win_width = w;
4448 mset.win_height = h;
4449
4450 //Override aspect ratio, is this ok?
4451 //mdat.video_aspect = mset.win_aspect();
4452
4453 mplayerwindow->setResolution( w, h );
4454 mplayerwindow->setAspect( mset.win_aspect() );
4455}
4456
4457void Core::gotNoVideo() {
4458 // File has no video (a sound file)
4459
4460 // Reduce size of window
4461 /*
4462 mset.win_width = mplayerwindow->size().width();
4463 mset.win_height = 0;
4464 mplayerwindow->setResolution( mset.win_width, mset.win_height );
4465 emit needResize( mset.win_width, mset.win_height );
4466 */
4467 //mplayerwindow->showLogo(true);
4468 emit noVideo();
4469}
4470
4471void Core::gotVO(QString vo) {
4472 qDebug() << "Core::gotVO:" << vo;
4473
4474 /*
4475 if (pref->vo.isEmpty()) {
4476 qDebug("Core::gotVO: saving vo");
4477 pref->vo = vo;
4478 }
4479 */
4480}
4481
4482void Core::gotAO(QString ao) {
4483 qDebug() << "Core::gotAO:" << ao;
4484
4485 /*
4486 if (pref->ao.isEmpty()) {
4487 qDebug("Core::gotAO: saving ao");
4488 pref->ao = ao;
4489 }
4490 */
4491}
4492
4493void Core::streamTitleChanged(QString title) {
4494 mdat.stream_title = title;
4495 emit mediaInfoChanged();
4496}
4497
4498void Core::streamTitleAndUrlChanged(QString title, QString url) {
4499 mdat.stream_title = title;
4500 mdat.stream_url = url;
4501 emit mediaInfoChanged();
4502}
4503
4504void Core::sendMediaInfo() {
4505 qDebug("Core::sendMediaInfo");
4506 emit mediaPlaying(mdat.filename, mdat.displayName(pref->show_tag_in_window_title));
4507}
4508
4509//! Called when the state changes
4510void Core::watchState(Core::State state) {
4511#ifdef SCREENSAVER_OFF
4512 #if 0
4513 qDebug("Core::watchState: %d", state);
4514 //qDebug("Core::watchState: has video: %d", !mdat.novideo);
4515
4516 if ((state == Playing) /* && (!mdat.novideo) */) {
4517 disableScreensaver();
4518 } else {
4519 enableScreensaver();
4520 }
4521 #endif
4522#endif
4523
4524 if ((proc->isMPlayer()) && (state == Playing) && (change_volume_after_unpause)) {
4525 // Delayed volume change
4526 qDebug("Core::watchState: delayed volume change");
4527 int volume = (pref->global_volume ? pref->volume : mset.volume);
4528 proc->setVolume(volume);
4529 change_volume_after_unpause = false;
4530 }
4531}
4532
4533void Core::checkIfVideoIsHD() {
4534 qDebug("Core::checkIfVideoIsHD");
4535
4536 // Check if the video is in HD and uses ffh264 codec.
4537 if ((mdat.video_codec=="ffh264") && (mset.win_height >= pref->HD_height)) {
4538 qDebug("Core::checkIfVideoIsHD: video == ffh264 and height >= %d", pref->HD_height);
4539 if (!mset.is264andHD) {
4540 mset.is264andHD = true;
4541 if (pref->h264_skip_loop_filter == Preferences::LoopDisabledOnHD) {
4542 qDebug("Core::checkIfVideoIsHD: we're about to restart the video");
4543 restartPlay();
4544 }
4545 }
4546 } else {
4547 mset.is264andHD = false;
4548 // FIXME: if the video was previously marked as HD, and now it's not
4549 // then the video should restart too.
4550 }
4551}
4552
4553#if DELAYED_AUDIO_SETUP_ON_STARTUP && NOTIFY_AUDIO_CHANGES
4554#error "DELAYED_AUDIO_SETUP_ON_STARTUP and NOTIFY_AUDIO_CHANGES can't be both defined"
4555#endif
4556
4557#if DELAYED_AUDIO_SETUP_ON_STARTUP
4558void Core::initAudioTrack() {
4559 qDebug("Core::initAudioTrack");
4560
4561 // First audio if none selected
4562 if ( (mset.current_audio_id == MediaSettings::NoneSelected) &&
4563 (mdat.audios.numItems() > 0) )
4564 {
4565 // Don't set mset.current_audio_id here! changeAudio will do.
4566 // Otherwise changeAudio will do nothing.
4567
4568 int audio = mdat.audios.itemAt(0).ID(); // First one
4569 if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) {
4570 audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID();
4571 }
4572
4573 // Check if one of the audio tracks is the user preferred.
4574 if (!pref->audio_lang.isEmpty()) {
4575 int res = mdat.audios.findLang( pref->audio_lang );
4576 if (res != -1) audio = res;
4577 }
4578
4579 changeAudio( audio );
4580 }
4581}
4582#endif
4583
4584#if NOTIFY_VIDEO_CHANGES
4585void Core::initVideoTrack(const Tracks & videos) {
4586 qDebug("Core::initVideoTrack");
4587 mdat.videos = videos;
4588 initializeMenus();
4589 updateWidgets();
4590}
4591#endif
4592
4593#if NOTIFY_AUDIO_CHANGES
4594void Core::initAudioTrack(const Tracks & audios) {
4595 qDebug("Core::initAudioTrack");
4596
4597 qDebug("Core::initAudioTrack: num_items: %d", mdat.audios.numItems());
4598
4599 bool restore_audio = ((mdat.audios.numItems() > 0) ||
4600 (mset.current_audio_id != MediaSettings::NoneSelected));
4601
4602 mdat.audios = audios;
4603
4604 qDebug("Core::initAudioTrack: list of audios:");
4605 mdat.audios.list();
4606
4607 initializeMenus();
4608
4609 if (!restore_audio) {
4610 // Select initial track
4611 qDebug("Core::initAudioTrack: selecting initial track");
4612
4613 bool change_audio = (mdat.type != TYPE_STREAM); // Don't change audio with streams unless strictly necessary
4614
4615 int audio = mdat.audios.itemAt(0).ID(); // First one
4616 if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) {
4617 audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID();
4618 }
4619
4620 // Check if one of the audio tracks is the user preferred.
4621 if (!pref->audio_lang.isEmpty()) {
4622 int res = mdat.audios.findLang( pref->audio_lang );
4623 if (res != -1) {
4624 audio = res;
4625 change_audio = true;
4626 }
4627 }
4628
4629 if (change_audio) changeAudio( audio );
4630 } else {
4631 // Try to restore previous audio track
4632 qDebug("Core::initAudioTrack: restoring audio");
4633 // Nothing to do, the audio is already set with -aid
4634 }
4635
4636 updateWidgets();
4637
4638 emit audioTracksChanged();
4639}
4640#endif
4641
4642#if NOTIFY_SUB_CHANGES
4643void Core::initSubtitleTrack(const SubTracks & subs) {
4644 qDebug("Core::initSubtitleTrack");
4645
4646 qDebug("Core::initSubtitleTrack: num_items: %d", mdat.subs.numItems());
4647
4648 bool restore_subs = ((mdat.subs.numItems() > 0) ||
4649 (mset.current_sub_id != MediaSettings::NoneSelected));
4650
4651 // Save current sub
4652 SubData::Type previous_sub_type = SubData::Sub;
4653 int previous_sub_id = -1;
4654 if (mdat.subs.numItems() > 0) {
4655 if ((mset.current_sub_id != MediaSettings::SubNone) &&
4656 (mset.current_sub_id != MediaSettings::NoneSelected))
4657 {
4658 previous_sub_type = mdat.subs.itemAt(mset.current_sub_id).type();
4659 previous_sub_id = mdat.subs.itemAt(mset.current_sub_id).ID();
4660 }
4661 }
4662 qDebug("Core::initSubtitleTrack: previous subtitle: type: %d id: %d", previous_sub_type, previous_sub_id);
4663
4664 mdat.subs = subs;
4665
4666 qDebug("Core::initSubtitleTrack: list of subtitles:");
4667 mdat.subs.list();
4668
4669 initializeMenus();
4670
4671 if (just_unloaded_external_subs) {
4672 qDebug("Core::initSubtitleTrack: just_unloaded_external_subs: true");
4673 restore_subs = false;
4674 just_unloaded_external_subs = false;
4675 }
4676 if (just_loaded_external_subs) {
4677 qDebug("Core::initSubtitleTrack: just_loaded_external_subs: true");
4678 restore_subs = false;
4679 just_loaded_external_subs = false;
4680
4681 QFileInfo fi(mset.external_subtitles);
4682 bool is_idx = (fi.suffix().toLower() == "idx");
4683 if (proc->isMPV()) is_idx = false; // Hack to ignore the idx extension with mpv
4684
4685 if (!is_idx) {
4686 // The loaded subtitle file is the last one, so
4687 // try to select that one.
4688 if (mdat.subs.numItems() > 0) {
4689 int selected_subtitle = mdat.subs.numItems()-1; // If everything fails, use the last one
4690
4691 // Try to find the subtitle file in the list
4692 for (int n = 0; n < mdat.subs.numItems(); n++) {
4693 SubData sub = mdat.subs.itemAt(n);
4694 if ((sub.type() == SubData::File) && (sub.filename() == mset.external_subtitles)) {
4695 selected_subtitle = n;
4696 qDebug("Core::initSubtitleTrack: external subtitle found: #%d", n);
4697 break;
4698 }
4699 }
4700 changeSubtitle( selected_subtitle );
4701 goto end;
4702 }
4703 }
4704 }
4705
4706 if (!restore_subs) {
4707 // Select initial track
4708 qDebug("Core::initSubtitleTrack: selecting initial track");
4709
4710 if (!pref->autoload_sub) {
4711 changeSubtitle( MediaSettings::SubNone );
4712 } else {
4713 //Select first subtitle
4714 int sub = mdat.subs.selectOne( pref->subtitle_lang, pref->initial_subtitle_track-1 );
4715 changeSubtitle( sub );
4716 }
4717 } else {
4718 // Try to restore previous subtitle track
4719 qDebug("Core::initSubtitleTrack: restoring subtitle");
4720
4721 if (mset.current_sub_id == MediaSettings::SubNone) {
4722 changeSubtitle( MediaSettings::SubNone );
4723 }
4724 else
4725 if (mset.current_sub_id != MediaSettings::NoneSelected) {
4726 // Try to find old subtitle
4727 int item = mset.current_sub_id;
4728 if (previous_sub_id != -1) {
4729 int sub_item = mdat.subs.find(previous_sub_type, previous_sub_id);
4730 if (sub_item > -1) {
4731 item = sub_item;
4732 qDebug("Core::initSubtitleTrack: previous subtitle found: %d", sub_item);
4733 }
4734 }
4735 if (item > -1) {
4736 changeSubtitle(item );
4737 } else {
4738 qDebug("Core::initSubtitleTrack: previous subtitle not found!");
4739 }
4740 }
4741 }
4742end:
4743
4744#ifdef MPV_SUPPORT
4745 changeSecondarySubtitle(mset.current_secondary_sub_id);
4746#endif
4747 updateWidgets();
4748}
4749
4750void Core::setSubtitleTrackAgain(const SubTracks &) {
4751 qDebug("Core::setSubtitleTrackAgain");
4752 changeSubtitle( mset.current_sub_id );
4753}
4754#endif
4755
4756#if NOTIFY_CHAPTER_CHANGES
4757void Core::updateChapterInfo(const Chapters & chapters) {
4758 qDebug("Core::updateChapterInfo");
4759 mdat.chapters = chapters;
4760 initializeMenus();
4761 updateWidgets();
4762}
4763#endif
4764
4765#if DVDNAV_SUPPORT
4766void Core::dvdTitleChanged(int title) {
4767 qDebug("Core::dvdTitleChanged: %d", title);
4768}
4769
4770void Core::durationChanged(double length) {
4771 qDebug("Core::durationChanged: %f", length);
4772 if (mdat.duration != length) {
4773 mdat.duration = length;
4774 emit newDuration(length);
4775 }
4776}
4777
4778void Core::askForInfo() {
4779 if (proc->isMPlayer()) {
4780 if ((state() == Playing) && (mdat.filename.startsWith("dvdnav:"))) {
4781 proc->setPausingPrefix(pausing_prefix());
4782 proc->askForLength();
4783 }
4784 }
4785}
4786
4787void Core::dvdnavUpdateMousePos(QPoint pos) {
4788#if 0
4789 bool under_mouse = mplayerwindow->videoLayer()->underMouse();
4790
4791 qDebug("Core::dvdnavUpdateMousePos: %d %d", pos.x(), pos.y());
4792 qDebug("Core::dvdnavUpdateMousePos: state: %d", state());
4793 qDebug("Core::dvdnavUpdateMousePos: filename: %s", mdat.filename.toUtf8().constData());
4794 qDebug("Core::dvdnavUpdateMousePos: dvdnav_title_is_menu: %d", dvdnav_title_is_menu);
4795 qDebug("Core::dvdnavUpdateMousePos: under mouse: %d", under_mouse);
4796#endif
4797 if ((state() == Playing) && (mdat.filename.startsWith("dvdnav:")) && (dvdnav_title_is_menu)) {
4798 //if (under_mouse) {
4799 proc->discSetMousePos(pos.x(), pos.y());
4800 //}
4801 }
4802}
4803
4804void Core::dvdTitleIsMenu() {
4805 qDebug("Core::dvdTitleIsMenu");
4806 dvdnav_title_is_menu = true;
4807}
4808
4809void Core::dvdTitleIsMovie() {
4810 qDebug("Core::dvdTitleIsMovie");
4811 dvdnav_title_is_menu = false;
4812}
4813#endif
4814
4815QString Core::pausing_prefix() {
4816 qDebug("Core::pausing_prefix");
4817
4818#ifdef MPLAYER2_SUPPORT
4819 if (MplayerVersion::isMplayer2()) {
4820 return QString::null;
4821 }
4822 else
4823#endif
4824 if ( (pref->use_pausing_keep_force) &&
4825 (MplayerVersion::isMplayerAtLeast(27665)) )
4826 {
4827 return "pausing_keep_force";
4828 } else {
4829 return "pausing_keep";
4830 }
4831}
4832
4833#ifdef BOOKMARKS
4834void Core::prevBookmark() {
4835 qDebug("Core::prevBookmark");
4836
4837 if (mset.bookmarks.count() > 0) {
4838 QMapIterator<int, QString> i(mset.bookmarks);
4839 i.toBack();
4840 int last_time = i.peekPrevious().key();
4841 while (i.hasPrevious()) {
4842 i.previous();
4843 int time = i.key();
4844 if (time < (mset.current_sec -2)) {
4845 goToSec(time);
4846 return;
4847 }
4848 }
4849 // Go to last bookmark
4850 goToSec(last_time);
4851 }
4852}
4853
4854void Core::nextBookmark() {
4855 qDebug("Core::nextBookmark");
4856
4857 if (mset.bookmarks.count() > 0) {
4858 QMapIterator<int, QString> i(mset.bookmarks);
4859 int first_time = i.peekNext().key();
4860 while (i.hasNext()) {
4861 i.next();
4862 int time = i.key();
4863 if (time > mset.current_sec) {
4864 goToSec(time);
4865 return;
4866 }
4867 }
4868 // Go to first bookmark
4869 goToSec(first_time);
4870 }
4871}
4872#endif
4873
4874#include "moc_core.cpp"
Note: See TracBrowser for help on using the repository browser.