1
1
/* smplayer, GUI front-end for mplayer.
2
Copyright (C) 2006-2013 Ricardo Villalba <rvm@users.sourceforge.net>
2
Copyright (C) 2006-2014 Ricardo Villalba <rvm@users.sourceforge.net>
4
4
This program is free software; you can redistribute it and/or modify
5
5
it under the terms of the GNU General Public License as published by
223
223
connect( proc, SIGNAL(receivedTitleIsMovie()),
224
224
this, SLOT(dvdTitleIsMovie()) );
227
connect( proc, SIGNAL(receivedForbiddenText()), this, SIGNAL(receivedForbidden()) );
227
229
connect( this, SIGNAL(stateChanged(Core::State)),
228
230
this, SLOT(watchState(Core::State)) );
244
246
mplayerwindow, SLOT(playingStarted()) );
246
248
#if DVDNAV_SUPPORT
247
connect( mplayerwindow, SIGNAL(mouseMoved(QPoint)),
249
connect( mplayerwindow->videoLayer(), SIGNAL(mouseMoved(QPoint)),
248
250
this, SLOT(dvdnavUpdateMousePos(QPoint)) );
257
259
#ifdef SCREENSAVER_OFF
258
260
// Windows or OS2 screensaver
259
261
win_screensaver = new WinScreenSaver();
262
connect( this, SIGNAL(aboutToStartPlaying()), this, SLOT(disableScreensaver()) );
263
connect( proc, SIGNAL(processExited()), this, SLOT(enableScreensaver()) );
264
connect( proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(enableScreensaver()) );
267
268
#ifdef YOUTUBE_SUPPORT
402
403
QString str = QString("osd_show_text \"%1\" %2 %3\n").arg(text.toUtf8().constData()).arg(duration).arg(level);
403
404
if (!prefix.isEmpty()) str = prefix + " " + str;
404
405
qDebug("Core::displayTextOnOSD: command: '%s'", str.toUtf8().constData());
405
proc->write(str.toAscii());
406
proc->write(str.toLatin1());
541
549
void Core::YTNoVideoUrl() {
542
emit showMessage( tr("Unable to locate the url of the video") );
550
emit showMessage( tr("Unable to locate the URL of the video") );
554
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
555
#ifdef SCREENSAVER_OFF
556
void Core::enableScreensaver() {
557
qDebug("Core::enableScreensaver");
558
if (pref->turn_screensaver_off) {
559
win_screensaver->enable();
563
void Core::disableScreensaver() {
564
qDebug("Core::disableScreensaver");
565
if (pref->turn_screensaver_off) {
566
win_screensaver->disable();
546
572
void Core::loadSub(const QString & sub ) {
605
631
QFileInfo fi(directory);
606
632
if ( (fi.exists()) && (fi.isDir()) ) {
607
633
pref->dvd_directory = directory;
608
pref->play_dvd_from_hd = TRUE;
634
pref->play_dvd_from_hd = true;
611
637
qDebug("Core::openDVD: directory '%s' is not valid", directory.toUtf8().data());
785
#ifdef BLURAY_SUPPORT
787
* Opens a BluRay, taking advantage of mplayer's capabilities to do so.
789
void Core::openBluRay(QString bluray_url) {
790
qDebug("Core::openBluRay: '%s'", bluray_url.toUtf8().data());
793
DiscData disc_data = DiscName::split(bluray_url);
794
QString folder = disc_data.device;
795
int title = disc_data.title;
798
qWarning("Core::openBluRay: title invalid, not playing bluray");
802
QFileInfo fi(folder);
803
if ( (!fi.exists()) || (!fi.isDir()) ) {
804
qWarning("Core::openBluRay: folder invalid, not playing bluray");
808
if (proc->isRunning()) {
810
we_are_restarting = false;
813
// Save data of previous file:
814
#ifndef NO_USE_INI_FILES
819
mdat.filename = bluray_url;
820
mdat.type = TYPE_BLURAY;
824
mset.current_title_id = title;
825
mset.current_chapter_id = firstChapter();
826
mset.current_angle_id = 1;
828
/* initializeMenus(); */
758
834
void Core::openTV(QString channel_id) {
759
835
qDebug("Core::openTV: '%s'", channel_id.toUtf8().constData());
813
889
qDebug("Core::openStream: '%s'", name.toUtf8().data());
815
891
#ifdef YOUTUBE_SUPPORT
816
if (name.contains("youtube.com/watch", Qt::CaseInsensitive) ||
817
name.contains("youtu.be/", Qt::CaseInsensitive) ||
818
name.contains("y2u.be/", Qt::CaseInsensitive) )
820
qDebug("Core::openStream: youtube url detected");
821
if (name.startsWith("www.youtube.com")) name = "http://" + name;
822
if (name.startsWith("youtube.com")) name = "http://www." + name;
823
if (name.startsWith("youtu.be")) name = "http://" + name;
824
if (name.startsWith("y2u.be")) name = "http://" + name;
892
// Check if the stream is a youtube url
893
QString yt_full_url = yt->fullUrl(name);
894
if (!yt_full_url.isEmpty()) {
895
qDebug("Core::openStream: youtube url detected: %s", yt_full_url.toLatin1().constData());
825
897
yt->setPreferredQuality( (RetrieveYoutubeUrl::Quality) pref->yt_quality );
826
898
qDebug("Core::openStream: user_agent: '%s'", pref->yt_user_agent.toUtf8().constData());
827
899
if (!pref->yt_user_agent.isEmpty()) yt->setUserAgent(pref->yt_user_agent);
828
900
#ifdef YT_USE_SCRIPT
829
YTSig::setScriptFile( Paths::configPath() + "/ytcode.script" );
901
YTSig::setScriptFile( Paths::configPath() + "/yt.js" );
831
903
yt->fetchPage(name);
1132
1204
changeAspectRatio(mset.aspect_ratio_id);
1134
if (pref->global_volume) {
1135
bool was_muted = pref->mute;
1136
setVolume( pref->volume, true);
1137
if (was_muted) mute(true);
1206
if (pref->mplayer_additional_options.contains("-volume")) {
1207
qDebug("Core::finishRestart: don't set volume since -volume is used");
1139
bool was_muted = mset.mute;
1140
setVolume( mset.volume, true );
1141
if (was_muted) mute(true);
1209
if (pref->global_volume) {
1210
bool was_muted = pref->mute;
1211
setVolume( pref->volume, true);
1212
if (was_muted) mute(true);
1214
bool was_muted = mset.mute;
1215
setVolume( mset.volume, true );
1216
if (was_muted) mute(true);
1144
1220
if (pref->change_video_equalizer_on_startup && (mset.gamma != 0)) {
1212
1287
qDebug("Core::play");
1214
1289
if ((proc->isRunning()) && (state()==Paused)) {
1215
1290
tellmp("pause"); // Unpauses
1218
1293
if ((proc->isRunning()) && (state()==Playing)) {
1219
1294
// nothing to do, continue playing
1301
1378
void Core::processFinished()
1303
1380
qDebug("Core::processFinished");
1305
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
1306
#ifdef SCREENSAVER_OFF
1307
// Restores the Windows or OS2 screensaver
1308
if (pref->turn_screensaver_off) {
1309
win_screensaver->enable();
1314
1381
qDebug("Core::processFinished: we_are_restarting: %d", we_are_restarting);
1316
1383
//mset.current_sec = 0;
1398
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
1399
#ifdef SCREENSAVER_OFF
1400
// Disable the Windows or OS2 screensaver
1401
if (pref->turn_screensaver_off) {
1402
win_screensaver->disable();
1407
1465
bool is_mkv = (QFileInfo(file).suffix().toLower() == "mkv");
1428
1486
qDebug("Core::startMplayer: checking if stream is a playlist");
1429
1487
qDebug("Core::startMplayer: url path: '%s'", url.path().toUtf8().constData());
1431
QRegExp rx("\\.ram$|\\.asx$|\\.m3u$|\\.pls$", Qt::CaseInsensitive);
1432
url_is_playlist = (rx.indexIn(url.path()) != -1);
1489
if (url.scheme().toLower() != "ffmpeg") {
1490
QRegExp rx("\\.ram$|\\.asx$|\\.m3u$|\\.m3u8$|\\.pls$", Qt::CaseInsensitive);
1491
url_is_playlist = (rx.indexIn(url.path()) != -1);
1434
1494
qDebug("Core::startMplayer: url_is_playlist: %d", url_is_playlist);
1497
// Check if a m4a file exists with the same name of file, in that cause if will be used as audio
1498
if (pref->autoload_m4a && mset.external_audio.isEmpty()) {
1500
if (fi.exists() && !fi.isDir()) {
1501
if (fi.suffix().toLower() == "mp4") {
1502
QString file2 = fi.path() + "/" + fi.completeBaseName() + ".m4a";
1503
//qDebug("Core::startMplayer: file2: %s", file2.toUtf8().constData());
1504
if (!QFile::exists(file2)) {
1505
// Check for upper case
1506
file2 = fi.path() + "/" + fi.completeBaseName() + ".M4A";
1508
if (QFile::exists(file2)) {
1509
qDebug("Core::startMplayer: found %s, so it will be used as audio file", file2.toUtf8().constData());
1510
mset.external_audio = file2;
1437
1517
bool screenshot_enabled = ( (pref->use_screenshot) &&
1438
1518
(!pref->screenshot_directory.isEmpty()) &&
1439
1519
(QFileInfo(pref->screenshot_directory).isDir()) );
1735
1815
proc->addArgument( "-ass-font-scale");
1736
1816
proc->addArgument( QString::number(mset.sub_scale_ass) );
1818
if (!pref->mplayer_is_mplayer2) {
1819
proc->addArgument( "-noflip-hebrew" ); // It seems to be necessary to display arabic subtitles correctly when using -ass
1738
1822
if (!pref->force_ass_styles) {
1739
1823
// Load the styles.ass file
1740
1824
if (!QFile::exists(Paths::subtitleStyleFile())) {
1759
1843
// Use the same font for OSD
1760
1844
#if !defined(Q_OS_OS2)
1761
if (!pref->ass_styles.fontname.isEmpty()) {
1845
if ((pref->use_fontconfig) && (!pref->ass_styles.fontname.isEmpty())) {
1762
1846
#ifdef USE_FONTCONFIG_OPTIONS
1763
1847
if (!pref->mplayer_is_mplayer2) { // -fontconfig removed from mplayer2
1764
1848
proc->addArgument("-fontconfig");
1860
1944
proc->addArgument( QString::number( mset.current_video_id ) );
1863
if (mset.current_audio_id != MediaSettings::NoneSelected) {
1864
// Workaround for MPlayer bug #1321 (http://bugzilla.mplayerhq.hu/show_bug.cgi?id=1321)
1865
if (mdat.audios.numItems() != 1) {
1866
proc->addArgument("-aid");
1867
proc->addArgument( QString::number( mset.current_audio_id ) );
1947
if (mset.external_audio.isEmpty()) {
1948
if (mset.current_audio_id != MediaSettings::NoneSelected) {
1949
// Workaround for MPlayer bug #1321 (http://bugzilla.mplayerhq.hu/show_bug.cgi?id=1321)
1950
if (mdat.audios.numItems() != 1) {
1951
proc->addArgument("-aid");
1952
proc->addArgument( QString::number( mset.current_audio_id ) );
1967
2053
// Set volume, requires mplayer svn r27872
1968
2054
bool use_volume_option = (MplayerVersion::isMplayerAtLeast(27872));
1970
if (pref->global_volume) {
1971
if (use_volume_option) {
1972
proc->addArgument("-volume");
1973
proc->addArgument( QString::number( pref->volume ) );
2056
if (pref->mplayer_additional_options.contains("-volume")) {
2057
qDebug("Core::startMplayer: don't set volume since -volume is used");
1976
if (use_volume_option) {
1977
proc->addArgument("-volume");
1978
// Note: mset.volume may not be right, it can be the volume of the previous video if
1979
// playing a new one, but I think it's better to use anyway the current volume on
1980
// startup than set it to 0 or something.
1981
// The right volume will be set later, when the video starts to play.
1982
proc->addArgument( QString::number( mset.volume ) );
2059
if (pref->global_volume) {
2060
if (use_volume_option) {
2061
proc->addArgument("-volume");
2062
proc->addArgument( QString::number( pref->volume ) );
2065
if (use_volume_option) {
2066
proc->addArgument("-volume");
2067
// Note: mset.volume may not be right, it can be the volume of the previous video if
2068
// playing a new one, but I think it's better to use anyway the current volume on
2069
// startup than set it to 0 or something.
2070
// The right volume will be set later, when the video starts to play.
2071
proc->addArgument( QString::number( mset.volume ) );
2018
2108
switch (mdat.type) {
2019
2109
case TYPE_FILE : cache = pref->cache_for_files; break;
2020
2110
case TYPE_DVD : cache = pref->cache_for_dvds;
2022
2112
if (file.startsWith("dvdnav:")) cache = 0;
2025
2115
case TYPE_STREAM : cache = pref->cache_for_streams; break;
2026
2116
case TYPE_VCD : cache = pref->cache_for_vcds; break;
2027
2117
case TYPE_AUDIO_CD : cache = pref->cache_for_audiocds; break;
2028
2118
case TYPE_TV : cache = pref->cache_for_tv; break;
2119
#ifdef BLURAY_SUPPORT
2120
case TYPE_BLURAY : cache = pref->cache_for_dvds; break; // FIXME: use cache for bluray?
2029
2122
default: cache = 0;
2311
2404
// Audio equalizer
2312
2405
if (pref->use_audio_equalizer) {
2313
2406
if (!af.isEmpty()) af += ",";
2314
af += "equalizer=" + Helper::equalizerListToString(mset.audio_equalizer);
2407
AudioEqualizerList l = pref->global_audio_equalizer ? pref->audio_equalizer : mset.audio_equalizer;
2408
af += "equalizer=" + Helper::equalizerListToString(l);
2349
2443
QFileInfo f(file);
2350
2444
QString basename = f.path() + "/" + f.completeBaseName();
2352
qDebug("Core::startMplayer: file basename: '%s'", basename.toUtf8().data());
2446
//qDebug("Core::startMplayer: file basename: '%s'", basename.toUtf8().data());
2354
2448
if (QFile::exists(basename+".edl"))
2355
2449
edl_f = basename+".edl";
2419
2513
QString line_for_log = commandline + "\n";
2420
2514
emit logLineAvailable(line_for_log);
2517
if (!pref->use_windowsfontdir) {
2518
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2519
env.insert("FONTCONFIG_FILE", Paths::configPath() + "/fonts.conf");
2520
proc->setProcessEnvironment(env);
2422
2523
if ( !proc->start() ) {
2423
2524
// error handling
2424
2525
qWarning("Core::startMplayer: mplayer process didn't start");
2891
2992
void Core::incBrightness() {
2892
setBrightness(mset.brightness + 4);
2993
setBrightness(mset.brightness + pref->min_step);
2895
2996
void Core::decBrightness() {
2896
setBrightness(mset.brightness - 4);
2997
setBrightness(mset.brightness - pref->min_step);
2899
3000
void Core::incContrast() {
2900
setContrast(mset.contrast + 4);
3001
setContrast(mset.contrast + pref->min_step);
2903
3004
void Core::decContrast() {
2904
setContrast(mset.contrast - 4);
3005
setContrast(mset.contrast - pref->min_step);
2907
3008
void Core::incGamma() {
2908
setGamma(mset.gamma + 4);
3009
setGamma(mset.gamma + pref->min_step);
2911
3012
void Core::decGamma() {
2912
setGamma(mset.gamma - 4);
3013
setGamma(mset.gamma - pref->min_step);
2915
3016
void Core::incHue() {
2916
setHue(mset.hue + 4);
3017
setHue(mset.hue + pref->min_step);
2919
3020
void Core::decHue() {
2920
setHue(mset.hue - 4);
3021
setHue(mset.hue - pref->min_step);
2923
3024
void Core::incSaturation() {
2924
setSaturation(mset.saturation + 4);
3025
setSaturation(mset.saturation + pref->min_step);
2927
3028
void Core::decSaturation() {
2928
setSaturation(mset.saturation - 4);
3029
setSaturation(mset.saturation - pref->min_step);
2931
3032
void Core::setSpeed( double value ) {
3041
3142
void Core::incVolume() {
3042
3143
qDebug("Core::incVolume");
3043
int new_vol = (pref->global_volume ? pref->volume + 4 : mset.volume + 4);
3144
int new_vol = (pref->global_volume ? pref->volume + pref->min_step : mset.volume + pref->min_step);
3044
3145
setVolume(new_vol);
3047
3148
void Core::decVolume() {
3048
3149
qDebug("Core::incVolume");
3049
int new_vol = (pref->global_volume ? pref->volume - 4 : mset.volume - 4);
3150
int new_vol = (pref->global_volume ? pref->volume - pref->min_step : mset.volume - pref->min_step);
3050
3151
setVolume(new_vol);
3199
3300
// Audio equalizer functions
3200
3301
void Core::setAudioEqualizer(AudioEqualizerList values, bool restart) {
3201
mset.audio_equalizer = values;
3302
if (pref->global_audio_equalizer) {
3303
pref->audio_equalizer = values;
3305
mset.audio_equalizer = values;
3203
3308
if (!restart) {
3204
3309
const char *command = "af_cmdline equalizer ";
3215
3320
void Core::updateAudioEqualizer() {
3216
setAudioEqualizer(mset.audio_equalizer);
3321
setAudioEqualizer(pref->global_audio_equalizer ? pref->audio_equalizer : mset.audio_equalizer);
3324
void Core::setAudioEq(int eq, int value) {
3325
if (pref->global_audio_equalizer) {
3326
pref->audio_equalizer[eq] = value;
3328
mset.audio_equalizer[eq] = value;
3330
updateAudioEqualizer();
3219
3333
void Core::setAudioEq0(int value) {
3220
mset.audio_equalizer[0] = value;
3221
updateAudioEqualizer();
3334
setAudioEq(0, value);
3224
3337
void Core::setAudioEq1(int value) {
3225
mset.audio_equalizer[1] = value;
3226
updateAudioEqualizer();
3338
setAudioEq(1, value);
3229
3341
void Core::setAudioEq2(int value) {
3230
mset.audio_equalizer[2] = value;
3231
updateAudioEqualizer();
3342
setAudioEq(2, value);
3234
3345
void Core::setAudioEq3(int value) {
3235
mset.audio_equalizer[3] = value;
3236
updateAudioEqualizer();
3346
setAudioEq(3, value);
3239
3349
void Core::setAudioEq4(int value) {
3240
mset.audio_equalizer[4] = value;
3241
updateAudioEqualizer();
3350
setAudioEq(4, value);
3244
3353
void Core::setAudioEq5(int value) {
3245
mset.audio_equalizer[5] = value;
3246
updateAudioEqualizer();
3354
setAudioEq(5, value);
3249
3357
void Core::setAudioEq6(int value) {
3250
mset.audio_equalizer[6] = value;
3251
updateAudioEqualizer();
3358
setAudioEq(6, value);
3254
3361
void Core::setAudioEq7(int value) {
3255
mset.audio_equalizer[7] = value;
3256
updateAudioEqualizer();
3362
setAudioEq(7, value);
3259
3365
void Core::setAudioEq8(int value) {
3260
mset.audio_equalizer[8] = value;
3261
updateAudioEqualizer();
3366
setAudioEq(8, value);
3264
3369
void Core::setAudioEq9(int value) {
3265
mset.audio_equalizer[9] = value;
3266
updateAudioEqualizer();
3370
setAudioEq(9, value);
3435
3539
// Workaround too for a mplayer problem in linux,
3436
3540
// the volume is reduced if using -softvol-max.
3438
if (pref->global_volume) {
3439
setVolume( pref->volume, true);
3440
if (pref->mute) mute(true);
3542
if (pref->mplayer_additional_options.contains("-volume")) {
3543
qDebug("Core::changeAudio: don't set volume since -volume is used");
3442
setVolume( mset.volume, true );
3443
if (mset.mute) mute(true); // if muted, mute again
3545
if (pref->global_volume) {
3546
setVolume( pref->volume, true);
3547
if (pref->mute) mute(true);
3549
setVolume( mset.volume, true );
3550
if (mset.mute) mute(true); // if muted, mute again
3445
3553
updateWidgets();
3546
3654
if (mdat.type == TYPE_DVD) {
3548
3656
if (mdat.filename.startsWith("dvdnav:")) {
3549
3657
tellmp("switch_title " + QString::number(ID));
3552
3660
DiscData disc_data = DiscName::split(mdat.filename);
3553
3661
disc_data.title = ID;
3554
3662
QString dvd_url = DiscName::join(disc_data);
3556
3664
openDVD( DiscName::join(disc_data) );
3669
#ifdef BLURAY_SUPPORT
3671
if (mdat.type == TYPE_BLURAY) {
3674
DiscData disc_data = DiscName::split(mdat.filename);
3675
disc_data.title = ID;
3676
QString bluray_url = DiscName::join(disc_data);
3677
qDebug("Core::changeTitle: bluray_url: %s", bluray_url.toUtf8().constData());
3678
openBluRay(bluray_url);
3563
3683
void Core::changeChapter(int ID) {
3679
3799
<< MediaSettings::Aspect11 // 1
3680
3800
<< MediaSettings::Aspect54 // 1.25
3681
3801
<< MediaSettings::Aspect43 // 1.33
3802
<< MediaSettings::Aspect118 // 1.37
3682
3803
<< MediaSettings::Aspect1410 // 1.4
3683
3804
<< MediaSettings::Aspect32 // 1.5
3684
3805
<< MediaSettings::Aspect149 // 1.55
4083
4204
mplayerwindow->setResolution( mset.win_width, mset.win_height );
4084
4205
emit needResize( mset.win_width, mset.win_height );
4086
//mplayerwindow->showLogo(TRUE);
4207
//mplayerwindow->showLogo(true);
4087
4208
emit noVideo();
4343
4464
void Core::durationChanged(double length) {
4344
4465
qDebug("Core::durationChanged: %f", length);
4345
mdat.duration = length;
4466
if (mdat.duration != length) {
4467
mdat.duration = length;
4468
emit newDuration(length);
4348
4472
void Core::askForInfo() {
4354
4478
void Core::dvdnavUpdateMousePos(QPoint pos) {
4479
//qDebug("Core::dvdnavUpdateMousePos");
4355
4480
if ((state() == Playing) && (mdat.filename.startsWith("dvdnav:")) && (dvdnav_title_is_menu)) {
4356
4481
if (mplayerwindow->videoLayer()->underMouse()) {
4357
QPoint p = mplayerwindow->videoLayer()->mapFromParent(pos);
4358
tellmp(QString("set_mouse_pos %1 %2").arg(p.x()).arg(p.y()));
4482
tellmp(QString("set_mouse_pos %1 %2").arg(pos.x()).arg(pos.y()));