source: smplayer/trunk/src/smplayer.cpp@ 168

Last change on this file since 168 was 165, checked in by Silvan Scherrer, 11 years ago

SMPlayer: update trunk to latest 0.8.7

  • Property svn:eol-style set to LF
File size: 17.2 KB
Line 
1/* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2014 Ricardo Villalba <rvm@users.sourceforge.net>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18
19#include "smplayer.h"
20#include "defaultgui.h"
21#include "minigui.h"
22#include "global.h"
23#include "paths.h"
24#include "translator.h"
25#include "version.h"
26#include "config.h"
27#include "clhelp.h"
28#include "cleanconfig.h"
29#include "myapplication.h"
30
31#ifdef MPCGUI
32#include "mpcgui.h"
33#endif
34
35#ifdef SKINS
36#include "skingui.h"
37#endif
38
39#include <QDir>
40#include <QUrl>
41#include <QTime>
42#include <stdio.h>
43
44#ifdef Q_OS_WIN
45#if USE_ASSOCIATIONS
46#include "extensions.h"
47#include "winfileassoc.h" //required for Uninstall
48#endif
49#endif
50
51#ifdef FONTCACHE_DIALOG
52#include "fontcache.h"
53#include "version.h"
54#endif
55
56using namespace Global;
57
58BaseGui * SMPlayer::main_window = 0;
59
60SMPlayer::SMPlayer(const QString & config_path, QObject * parent )
61 : QObject(parent)
62{
63#ifdef LOG_SMPLAYER
64 #if QT_VERSION >= 0x050000
65 qInstallMessageHandler( SMPlayer::myMessageOutput );
66 #else
67 qInstallMsgHandler( SMPlayer::myMessageOutput );
68 #endif
69 allow_to_send_log_to_gui = true;
70#endif
71
72 gui_to_use = "DefaultGUI";
73
74 close_at_end = -1; // Not set
75 start_in_fullscreen = -1; // Not set
76
77 move_gui = false;
78 resize_gui = false;
79
80 Paths::setAppPath( qApp->applicationDirPath() );
81
82#ifndef PORTABLE_APP
83 if (config_path.isEmpty()) createConfigDirectory();
84#endif
85 global_init(config_path);
86
87 // Application translations
88 translator->load( pref->language );
89 showInfo();
90
91#ifdef Q_OS_WIN
92 createFontFile();
93#endif
94}
95
96SMPlayer::~SMPlayer() {
97 if (main_window != 0) {
98 deleteGUI();
99 }
100 global_end();
101
102#ifdef LOG_SMPLAYER
103 if (output_log.isOpen()) output_log.close();
104#endif
105}
106
107BaseGui * SMPlayer::gui() {
108 if (main_window == 0) {
109 // Changes to app path, so smplayer can find a relative mplayer path
110 QDir::setCurrent(Paths::appPath());
111 qDebug("SMPlayer::gui: changed working directory to app path");
112 qDebug("SMPlayer::gui: current directory: %s", QDir::currentPath().toUtf8().data());
113
114#ifdef SKINS
115 if (gui_to_use == "SkinGUI") {
116 QString theme = pref->iconset;
117 if (theme.isEmpty()) theme = "Gonzo";
118 QString user_theme_dir = Paths::configPath() + "/themes/" + theme;
119 QString theme_dir = Paths::themesPath() + "/" + theme;
120 qDebug("SMPlayer::gui: user_theme_dir: %s", user_theme_dir.toUtf8().constData());
121 qDebug("SMPlayer::gui: theme_dir: %s", theme_dir.toUtf8().constData());
122 if ((QDir(theme_dir).exists()) || (QDir(user_theme_dir).exists())) {
123 if (pref->iconset.isEmpty()) pref->iconset = theme;
124 } else {
125 qDebug("SMPlayer::gui: skin folder doesn't exist. Falling back to default gui.");
126 gui_to_use = "DefaultGUI";
127 pref->iconset = "";
128 pref->gui = gui_to_use;
129 }
130 }
131#endif
132
133 main_window = createGUI(gui_to_use);
134
135 if (move_gui) {
136 qDebug("SMPlayer::gui: moving main window to %d %d", gui_position.x(), gui_position.y());
137 main_window->move(gui_position);
138 }
139 if (resize_gui) {
140 qDebug("SMPlayer::gui: resizing main window to %dx%d", gui_size.width(), gui_size.height());
141 main_window->resize(gui_size);
142 }
143 }
144
145 return main_window;
146}
147
148BaseGui * SMPlayer::createGUI(QString gui_name) {
149 BaseGui * gui = 0;
150
151#ifdef SKINS
152 if (gui_name.toLower() == "skingui")
153 gui = new SkinGui(0);
154 else
155#endif
156 if (gui_name.toLower() == "minigui")
157 gui = new MiniGui(0);
158 else
159#ifdef MPCGUI
160 if (gui_name.toLower() == "mpcgui")
161 gui = new MpcGui(0);
162 else
163#endif
164 gui = new DefaultGui(0);
165
166 gui->setForceCloseOnFinish(close_at_end);
167 gui->setForceStartInFullscreen(start_in_fullscreen);
168 connect(gui, SIGNAL(quitSolicited()), qApp, SLOT(quit()));
169
170#ifdef GUI_CHANGE_ON_RUNTIME
171 connect(gui, SIGNAL(guiChanged(QString)), this, SLOT(changeGUI(QString)));
172#endif
173
174#if SINGLE_INSTANCE
175 MyApplication * app = MyApplication::instance();
176 connect(app, SIGNAL(messageReceived(const QString&)),
177 gui, SLOT(handleMessageFromOtherInstances(const QString&)));
178 app->setActivationWindow(gui);
179#endif
180
181 return gui;
182}
183
184void SMPlayer::deleteGUI() {
185#ifdef LOG_SMPLAYER
186 allow_to_send_log_to_gui = false;
187#endif
188
189 delete main_window;
190 main_window = 0;
191
192#ifdef LOG_SMPLAYER
193 allow_to_send_log_to_gui = true;
194#endif
195}
196
197#ifdef GUI_CHANGE_ON_RUNTIME
198void SMPlayer::changeGUI(QString new_gui) {
199 qDebug("SMPlayer::changeGUI: '%s'", new_gui.toLatin1().constData());
200
201 deleteGUI();
202
203 main_window = createGUI(new_gui);
204
205 main_window->show();
206}
207#endif
208
209SMPlayer::ExitCode SMPlayer::processArgs(QStringList args) {
210 qDebug("SMPlayer::processArgs: arguments: %d", args.count());
211 for (int n = 0; n < args.count(); n++) {
212 qDebug("SMPlayer::processArgs: %d = %s", n, args[n].toUtf8().data());
213 }
214
215
216 QString action; // Action to be passed to running instance
217 bool show_help = false;
218
219 if (!pref->gui.isEmpty()) gui_to_use = pref->gui;
220 bool add_to_playlist = false;
221
222#ifdef Q_OS_WIN
223 if (args.contains("-uninstall")) {
224 #if USE_ASSOCIATIONS
225 //Called by uninstaller. Will restore old associations.
226 WinFileAssoc RegAssoc;
227 Extensions exts;
228 QStringList regExts;
229 RegAssoc.GetRegisteredExtensions(exts.multimedia(), regExts);
230 RegAssoc.RestoreFileAssociations(regExts);
231 printf("Restored associations\n");
232 #endif
233 return NoError;
234 }
235#endif
236
237 if (args.contains("-delete-config")) {
238 CleanConfig::clean(Paths::configPath());
239 return NoError;
240 }
241
242 for (int n = 1; n < args.count(); n++) {
243 QString argument = args[n];
244
245 if (argument == "-send-action") {
246 if (n+1 < args.count()) {
247 n++;
248 action = args[n];
249 } else {
250 printf("Error: expected parameter for -send-action\r\n");
251 return ErrorArgument;
252 }
253 }
254 else
255 if (argument == "-actions") {
256 if (n+1 < args.count()) {
257 n++;
258 actions_list = args[n];
259 } else {
260 printf("Error: expected parameter for -actions\r\n");
261 return ErrorArgument;
262 }
263 }
264 else
265 if (argument == "-sub") {
266 if (n+1 < args.count()) {
267 n++;
268 QString file = args[n];
269 if (QFile::exists(file)) {
270 subtitle_file = QFileInfo(file).absoluteFilePath();
271 } else {
272 printf("Error: file '%s' doesn't exists\r\n", file.toUtf8().constData());
273 }
274 } else {
275 printf("Error: expected parameter for -sub\r\n");
276 return ErrorArgument;
277 }
278 }
279 else
280 if (argument == "-pos") {
281 if (n+2 < args.count()) {
282 bool ok_x, ok_y;
283 n++;
284 gui_position.setX( args[n].toInt(&ok_x) );
285 n++;
286 gui_position.setY( args[n].toInt(&ok_y) );
287 if (ok_x && ok_y) move_gui = true;
288 } else {
289 printf("Error: expected parameter for -pos\r\n");
290 return ErrorArgument;
291 }
292 }
293 else
294 if (argument == "-size") {
295 if (n+2 < args.count()) {
296 bool ok_width, ok_height;
297 n++;
298 gui_size.setWidth( args[n].toInt(&ok_width) );
299 n++;
300 gui_size.setHeight( args[n].toInt(&ok_height) );
301 if (ok_width && ok_height) resize_gui = true;
302 } else {
303 printf("Error: expected parameter for -resize\r\n");
304 return ErrorArgument;
305 }
306 }
307 else
308 if ((argument == "--help") || (argument == "-help") ||
309 (argument == "-h") || (argument == "-?") )
310 {
311 show_help = true;
312 }
313 else
314 if (argument == "-close-at-end") {
315 close_at_end = 1;
316 }
317 else
318 if (argument == "-no-close-at-end") {
319 close_at_end = 0;
320 }
321 else
322 if (argument == "-fullscreen") {
323 start_in_fullscreen = 1;
324 }
325 else
326 if (argument == "-no-fullscreen") {
327 start_in_fullscreen = 0;
328 }
329 else
330 if (argument == "-add-to-playlist") {
331 add_to_playlist = true;
332 }
333 else
334 if (argument == "-mini" || argument == "-minigui") {
335 gui_to_use = "MiniGUI";
336 }
337 else
338 if (argument == "-mpcgui") {
339 gui_to_use = "MpcGUI";
340 }
341 else
342 if (argument == "-defaultgui") {
343 gui_to_use = "DefaultGUI";
344 }
345#ifdef SKINS
346 else
347 if (argument == "-skingui") {
348 gui_to_use = "SkinGUI";
349 }
350#endif
351 else {
352 // File
353 #if QT_VERSION >= 0x040600
354 QUrl fUrl = QUrl::fromUserInput(argument);
355 if (fUrl.isValid() && fUrl.scheme().toLower() == "file") {
356 argument = fUrl.toLocalFile();
357 }
358 #endif
359 if (QFile::exists( argument )) {
360 argument = QFileInfo(argument).absoluteFilePath();
361 }
362 files_to_play.append( argument );
363 }
364 }
365
366 if (show_help) {
367 printf("%s\n", CLHelp::help().toLocal8Bit().data());
368 return NoError;
369 }
370
371 qDebug("SMPlayer::processArgs: files_to_play: count: %d", files_to_play.count() );
372 for (int n=0; n < files_to_play.count(); n++) {
373 qDebug("SMPlayer::processArgs: files_to_play[%d]: '%s'", n, files_to_play[n].toUtf8().data());
374 }
375
376#ifdef SINGLE_INSTANCE
377 if (pref->use_single_instance) {
378 // Single instance
379 MyApplication * a = MyApplication::instance();
380 if (a->isRunning()) {
381 a->sendMessage("Hello");
382
383 if (!action.isEmpty()) {
384 a->sendMessage("action " + action);
385 }
386 else {
387 if (!subtitle_file.isEmpty()) {
388 a->sendMessage("load_sub " + subtitle_file);
389 }
390
391 if (!files_to_play.isEmpty()) {
392 /* a->sendMessage("open_file " + files_to_play[0]); */
393 QString command = "open_files";
394 if (add_to_playlist) command = "add_to_playlist";
395 a->sendMessage(command +" "+ files_to_play.join(" <<sep>> "));
396 }
397 }
398
399 return NoError;
400 }
401 }
402#endif
403
404 if (!pref->default_font.isEmpty()) {
405 QFont f;
406 f.fromString(pref->default_font);
407 qApp->setFont(f);
408 }
409
410 return SMPlayer::NoExit;
411}
412
413void SMPlayer::start() {
414#ifdef FONTCACHE_DIALOG
415#ifndef PORTABLE_APP
416 if (Version::with_revision() != pref->smplayer_version) {
417 FontCacheDialog d(0);
418 d.run(pref->mplayer_bin, "sample.avi");
419 pref->smplayer_version = Version::with_revision();
420 }
421#endif
422#endif
423
424 if (!gui()->startHidden() || !files_to_play.isEmpty() ) gui()->show();
425 if (!files_to_play.isEmpty()) {
426 if (!subtitle_file.isEmpty()) gui()->setInitialSubtitle(subtitle_file);
427 gui()->openFiles(files_to_play);
428 }
429
430 if (!actions_list.isEmpty()) {
431 if (files_to_play.isEmpty()) {
432 gui()->runActions(actions_list);
433 } else {
434 gui()->runActionsLater(actions_list);
435 }
436 }
437}
438
439#ifndef PORTABLE_APP
440void SMPlayer::createConfigDirectory() {
441 // Create smplayer config directory
442 if (!QFile::exists(Paths::configPath())) {
443 QDir d;
444 if (!d.mkdir(Paths::configPath())) {
445 qWarning("SMPlayer::createConfigDirectory: can't create %s", Paths::configPath().toUtf8().data());
446 }
447 // Screenshot folder already created in preferences.cpp if Qt >= 4.4
448 #if QT_VERSION < 0x040400
449 QString s = Paths::configPath() + "/screenshots";
450 if (!d.mkdir(s)) {
451 qWarning("SMPlayer::createHomeDirectory: can't create %s", s.toUtf8().data());
452 }
453 #endif
454 }
455}
456#endif
457
458#ifdef Q_OS_WIN
459void SMPlayer::createFontFile() {
460 qDebug("SMPlayer::createFontFile");
461 QString output = Paths::configPath() + "/fonts.conf";
462
463 // Check if the file already exists with the modified path
464 if (QFile::exists(output)) {
465 QFile i(output);
466 if (i.open(QIODevice::ReadOnly | QIODevice::Text)) {
467 QString text = i.readAll();
468 if (text.contains("<dir>" + Paths::fontPath() + "</dir>")) {
469 qDebug("SMPlayer::createFontFile: file %s already exists with font path. Doing nothing.", output.toUtf8().constData());
470 return;
471 }
472 }
473 }
474
475 QString input = Paths::appPath() + "/mplayer/fonts/fonts.conf";
476 qDebug("SMPlayer::createFontFile: input: %s", input.toLatin1().constData());
477 QFile infile(input);
478 if (infile.open(QIODevice::ReadOnly | QIODevice::Text)) {
479 QString text = infile.readAll();
480 text = text.replace("<dir>WINDOWSFONTDIR</dir>", "<dir>" + Paths::fontPath() + "</dir>");
481 //qDebug("SMPlayer::createFontFile: %s", text.toUtf8().constData());
482
483 qDebug("SMPlayer::createFontFile: saving %s", output.toUtf8().constData());
484 QFile outfile(output);
485 if (outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
486 outfile.write(text.toUtf8());
487 outfile.close();
488 }
489 }
490}
491#endif
492
493void SMPlayer::showInfo() {
494#ifdef Q_OS_WIN
495 QString win_ver;
496 switch (QSysInfo::WindowsVersion) {
497 case QSysInfo::WV_2000: win_ver = "Windows 2000"; break;
498 case QSysInfo::WV_XP: win_ver = "Windows XP"; break;
499 case QSysInfo::WV_2003: win_ver = "Windows XP Professional x64/Server 2003"; break;
500 case QSysInfo::WV_VISTA: win_ver = "Windows Vista/Server 2008"; break;
501 #if QT_VERSION >= 0x040501
502 case QSysInfo::WV_WINDOWS7: win_ver = "Windows 7/Server 2008 R2"; break;
503 #endif
504 #if QT_VERSION >= 0x040803
505 case QSysInfo::WV_WINDOWS8: win_ver = "Windows 8/Server 2012"; break;
506 #endif
507 case QSysInfo::WV_NT_based: win_ver = "NT-based Windows"; break;
508 default: win_ver = QString("Unknown/Unsupported Windows OS"); break;
509 }
510#endif
511 QString s = QObject::tr("This is SMPlayer v. %1 running on %2")
512 .arg(Version::printable())
513#ifdef Q_OS_LINUX
514 .arg("Linux")
515#else
516#ifdef Q_OS_WIN
517 .arg("Windows ("+win_ver+")")
518#else
519#ifdef Q_OS_OS2
520 .arg("eCS (OS/2)")
521#else
522 .arg("Other OS")
523#endif
524#endif
525#endif
526 ;
527
528 printf("%s\n", s.toLocal8Bit().data() );
529 qDebug("%s", s.toUtf8().data() );
530 qDebug("Compiled with Qt v. %s, using %s", QT_VERSION_STR, qVersion());
531
532 qDebug(" * application path: '%s'", Paths::appPath().toUtf8().data());
533 qDebug(" * data path: '%s'", Paths::dataPath().toUtf8().data());
534 qDebug(" * translation path: '%s'", Paths::translationPath().toUtf8().data());
535 qDebug(" * doc path: '%s'", Paths::docPath().toUtf8().data());
536 qDebug(" * themes path: '%s'", Paths::themesPath().toUtf8().data());
537 qDebug(" * shortcuts path: '%s'", Paths::shortcutsPath().toUtf8().data());
538 qDebug(" * config path: '%s'", Paths::configPath().toUtf8().data());
539 qDebug(" * ini path: '%s'", Paths::iniPath().toUtf8().data());
540 qDebug(" * file for subtitles' styles: '%s'", Paths::subtitleStyleFile().toUtf8().data());
541 qDebug(" * current path: '%s'", QDir::currentPath().toUtf8().data());
542#ifdef Q_OS_WIN
543 qDebug(" * font path: '%s'", Paths::fontPath().toUtf8().data());
544#endif
545}
546
547#ifdef LOG_SMPLAYER
548QFile SMPlayer::output_log;
549bool SMPlayer::allow_to_send_log_to_gui = false;
550
551#if QT_VERSION >= 0x050000
552void SMPlayer::myMessageOutput( QtMsgType type, const QMessageLogContext &, const QString & msg ) {
553#else
554void SMPlayer::myMessageOutput( QtMsgType type, const char *msg ) {
555#endif
556 static QStringList saved_lines;
557 static QString orig_line;
558 static QString line2;
559 static QRegExp rx_log;
560
561 if (pref) {
562 if (!pref->log_smplayer) return;
563 rx_log.setPattern(pref->log_filter);
564 } else {
565 rx_log.setPattern(".*");
566 }
567
568 line2.clear();
569
570#if QT_VERSION >= 0x050000
571 orig_line = msg;
572#else
573 orig_line = QString::fromUtf8(msg);
574#endif
575
576 switch ( type ) {
577 case QtDebugMsg:
578 if (rx_log.indexIn(orig_line) > -1) {
579 #ifndef NO_DEBUG_ON_CONSOLE
580 fprintf( stderr, "Debug: %s\n", orig_line.toLocal8Bit().data() );
581 #endif
582 line2 = orig_line;
583 }
584 break;
585 case QtWarningMsg:
586 #ifndef NO_DEBUG_ON_CONSOLE
587 fprintf( stderr, "Warning: %s\n", orig_line.toLocal8Bit().data() );
588 #endif
589 line2 = "WARNING: " + orig_line;
590 break;
591 case QtFatalMsg:
592 #ifndef NO_DEBUG_ON_CONSOLE
593 fprintf( stderr, "Fatal: %s\n", orig_line.toLocal8Bit().data() );
594 #endif
595 line2 = "FATAL: " + orig_line;
596 abort(); // deliberately core dump
597 case QtCriticalMsg:
598 #ifndef NO_DEBUG_ON_CONSOLE
599 fprintf( stderr, "Critical: %s\n", orig_line.toLocal8Bit().data() );
600 #endif
601 line2 = "CRITICAL: " + orig_line;
602 break;
603 }
604
605 if (line2.isEmpty()) return;
606
607 line2 = "["+ QTime::currentTime().toString("hh:mm:ss:zzz") +"] "+ line2;
608
609 if (allow_to_send_log_to_gui && main_window) {
610 if (!saved_lines.isEmpty()) {
611 // Send saved lines first
612 for (int n=0; n < saved_lines.count(); n++) {
613 main_window->recordSmplayerLog(saved_lines[n]);
614 }
615 saved_lines.clear();
616 }
617 main_window->recordSmplayerLog(line2);
618 } else {
619 // GUI is not created yet, save lines for later
620 saved_lines.append(line2);
621 /* printf("SMPlayer::myMessageOutput: no gui\n"); */
622 }
623
624 if (pref) {
625 if (pref->save_smplayer_log) {
626 // Save log to file
627 if (!output_log.isOpen()) {
628 // FIXME: the config path may not be initialized if USE_LOCKS is not defined
629 output_log.setFileName( Paths::configPath() + "/smplayer_log.txt" );
630 output_log.open(QIODevice::WriteOnly);
631 }
632 if (output_log.isOpen()) {
633 QString l = line2 + "\r\n";
634 output_log.write(l.toUtf8().constData());
635 output_log.flush();
636 }
637 }
638 }
639}
640#endif
641
642/*
643void myMessageOutput( QtMsgType type, const char *msg ) {
644 static QString orig_line;
645 orig_line = QString::fromUtf8(msg);
646
647 switch ( type ) {
648 case QtDebugMsg:
649 #ifndef NO_DEBUG_ON_CONSOLE
650 fprintf( stderr, "Debug: %s\n", orig_line.toLocal8Bit().data() );
651 #endif
652 break;
653
654 case QtWarningMsg:
655 #ifndef NO_DEBUG_ON_CONSOLE
656 fprintf( stderr, "Warning: %s\n", orig_line.toLocal8Bit().data() );
657 #endif
658 break;
659
660 case QtCriticalMsg:
661 #ifndef NO_DEBUG_ON_CONSOLE
662 fprintf( stderr, "Critical: %s\n", orig_line.toLocal8Bit().data() );
663 #endif
664 break;
665
666 case QtFatalMsg:
667 #ifndef NO_DEBUG_ON_CONSOLE
668 fprintf( stderr, "Fatal: %s\n", orig_line.toLocal8Bit().data() );
669 #endif
670 abort(); // deliberately core dump
671 }
672}
673*/
674
675#include "moc_smplayer.cpp"
Note: See TracBrowser for help on using the repository browser.