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