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