source: smplayer/trunk/src/mpvprocess.cpp@ 176

Last change on this file since 176 was 176, checked in by Silvan Scherrer, 9 years ago

smplayer: update trunk to version 16.4

File size: 21.9 KB
Line 
1/* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2016 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 "mpvprocess.h"
20#include <QRegExp>
21#include <QStringList>
22#include <QApplication>
23#include <QDebug>
24
25#include "global.h"
26#include "preferences.h"
27#include "mplayerversion.h"
28#include "colorutils.h"
29
30using namespace Global;
31
32#define CUSTOM_STATUS
33
34#define TOO_CHAPTERS_WORKAROUND
35
36MPVProcess::MPVProcess(QObject * parent)
37 : PlayerProcess(parent)
38 , notified_mplayer_is_running(false)
39 , notified_pause(false)
40 , received_end_of_file(false)
41 , last_sub_id(-1)
42 , mplayer_svn(-1) // Not found yet
43 , verbose(false)
44#if NOTIFY_SUB_CHANGES
45 , subtitle_info_received(false)
46 , subtitle_info_changed(false)
47#endif
48#if NOTIFY_AUDIO_CHANGES
49 , audio_info_changed(false)
50#endif
51#if NOTIFY_VIDEO_CHANGES
52 , video_info_changed(false)
53#endif
54#if NOTIFY_CHAPTER_CHANGES
55 , chapter_info_changed(false)
56#endif
57 , dvd_current_title(-1)
58 , br_current_title(-1)
59{
60 player_id = PlayerID::MPV;
61
62 connect( this, SIGNAL(lineAvailable(QByteArray)),
63 this, SLOT(parseLine(QByteArray)) );
64
65 connect( this, SIGNAL(finished(int,QProcess::ExitStatus)),
66 this, SLOT(processFinished(int,QProcess::ExitStatus)) );
67
68 connect( this, SIGNAL(error(QProcess::ProcessError)),
69 this, SLOT(gotError(QProcess::ProcessError)) );
70
71 /* int svn = MplayerVersion::mplayerVersion("mpv unknown version (C)"); */
72}
73
74MPVProcess::~MPVProcess() {
75}
76
77bool MPVProcess::start() {
78 md.reset();
79 notified_mplayer_is_running = false;
80 notified_pause = false;
81 last_sub_id = -1;
82 mplayer_svn = -1; // Not found yet
83 received_end_of_file = false;
84
85#if NOTIFY_SUB_CHANGES
86 subs.clear();
87 subtitle_info_received = false;
88 subtitle_info_changed = false;
89#endif
90
91#if NOTIFY_AUDIO_CHANGES
92 audios.clear();
93 audio_info_changed = false;
94#endif
95
96#if NOTIFY_VIDEO_CHANGES
97 videos.clear();
98 video_info_changed = false;
99#endif
100
101#if NOTIFY_CHAPTER_CHANGES
102 chapters.clear();
103 chapter_info_changed = false;
104#endif
105
106 dvd_current_title = -1;
107 br_current_title = -1;
108
109 MyProcess::start();
110
111 return waitForStarted();
112}
113
114#ifdef CUSTOM_STATUS
115static QRegExp rx_mpv_av("^STATUS: ([0-9\\.-]+) / ([0-9\\.-]+) P: (yes|no) B: (yes|no) I: (yes|no)");
116#else
117static QRegExp rx_mpv_av("^(\\((.*)\\) |)(AV|V|A): ([0-9]+):([0-9]+):([0-9]+) / ([0-9]+):([0-9]+):([0-9]+)"); //AV: 00:02:15 / 00:09:56
118#endif
119
120static QRegExp rx_mpv_dsize("^INFO_VIDEO_DSIZE=(\\d+)x(\\d+)");
121static QRegExp rx_mpv_vo("^VO: \\[(.*)\\]");
122static QRegExp rx_mpv_ao("^AO: \\[(.*)\\]");
123static QRegExp rx_mpv_paused("^\\(Paused\\)");
124static QRegExp rx_mpv_endoffile("^Exiting... \\(End of file\\)");
125
126//static QRegExp rx_mpv_audio("^\\[stream\\] Audio .* --aid=(\\d+)( --alang=([a-z]+)|)([ \\(\\)\\*]+)('(.*)'|)");
127static QRegExp rx_mpv_audio("^.* Audio\\s+--aid=(\\d+)( --alang=([a-z]+)|)([ \\(\\)\\*]+)('(.*)'|)");
128//static QRegExp rx_mpv_subs("^\\[stream\\] Subs .* --sid=(\\d+)( --slang=([a-z]+)|)([ \\(\\)\\*]+)('(.*)'|)");
129static QRegExp rx_mpv_subs("^.* Subs\\s+--sid=(\\d+)( --slang=([a-z]+)|)([ \\(\\)\\*]+)('(.*)'|)");
130#if !NOTIFY_VIDEO_CHANGES
131//static QRegExp rx_mpv_video("^\\[stream\\] Video .* --vid=(\\d+)([ \\(\\)\\*]+)('(.*)'|)");
132static QRegExp rx_mpv_video("^.* Video\\s+--vid=(\\d+)([ \\(\\)\\*]+)('(.*)'|)");
133#endif
134
135#if 0
136static QRegExp rx_mpv_subs2("^Sub:( >|) \\((\\d+)\\) '(.*)'");
137#endif
138
139static QRegExp rx_mpv_chaptername("^INFO_CHAPTER_(\\d+)_NAME=(.*)");
140static QRegExp rx_mpv_trackinfo("^INFO_TRACK_(\\d+): (audio|video|sub) (\\d+) '(.*)' '(.*)' (yes|no)");
141
142#if 0
143static QRegExp rx_mpv_videoinfo("^\\[vd\\] VIDEO: .* (\\d+)x(\\d+) .* ([0-9.]+) fps"); // [vd] VIDEO: 624x352 25.000 fps 1018.5 kbps (127.3 kB/s)
144#endif
145
146static QRegExp rx_mpv_videocodec("^INFO_VIDEO_CODEC=(.*) \\[(.*)\\]");
147static QRegExp rx_mpv_audiocodec("^INFO_AUDIO_CODEC=(.*) \\[(.*)\\]");
148
149static QRegExp rx_mpv_forbidden("HTTP error 403 Forbidden");
150
151#if DVDNAV_SUPPORT
152static QRegExp rx_mpv_switch_title("^\\[dvdnav\\] DVDNAV, switched to title: (\\d+)");
153#endif
154
155static QRegExp rx_mpv_playing("^Playing:.*|^\\[ytdl_hook\\].*");
156
157//static QRegExp rx_mpv_generic("^(.*)=(.*)");
158static QRegExp rx_mpv_generic("^([A-Z_]+)=(.*)");
159
160static QRegExp rx_mpv_stream_title("icy-title: (.*)");
161
162static QRegExp rx_mpv_debug("^(INFO|METADATA)_.*=\\$.*");
163
164void MPVProcess::parseLine(QByteArray ba) {
165 //qDebug("MPVProcess::parseLine: '%s'", ba.data() );
166
167 if (ba.isEmpty()) return;
168
169 QString tag;
170 QString value;
171
172#if COLOR_OUTPUT_SUPPORT
173 QString line = ColorUtils::stripColorsTags(QString::fromLocal8Bit(ba));
174#else
175 #ifdef Q_OS_WIN
176 QString line = QString::fromUtf8(ba);
177 #else
178 QString line = QString::fromLocal8Bit(ba);
179 #endif
180#endif
181
182 if (verbose) {
183 line.replace("[statusline] ", "");
184 line.replace("[cplayer] ", "");
185 line.replace("[term-msg] ", "");
186
187 if (rx_mpv_debug.indexIn(line) > -1) {
188 line = "[debug] " + line;
189 }
190 }
191
192 // Parse A: V: line
193 //qDebug("MPVProcess::parseLine: %s", line.toUtf8().data());
194 if (rx_mpv_av.indexIn(line) > -1) {
195 #ifdef CUSTOM_STATUS
196 double sec = rx_mpv_av.cap(1).toDouble();
197 double length = rx_mpv_av.cap(2).toDouble();
198 bool paused = (rx_mpv_av.cap(3) == "yes");
199 bool buffering = (rx_mpv_av.cap(4) == "yes");
200 bool idle = (rx_mpv_av.cap(5) == "yes");
201
202 if (length != md.duration) {
203 md.duration = length;
204 #if DVDNAV_SUPPORT
205 emit receivedDuration(length);
206 #endif
207 }
208
209 if (paused && notified_pause) return;
210
211 if (paused) {
212 notified_pause = true;
213 qDebug("MPVProcess::parseLine: paused");
214 receivedPause();
215 return;
216 }
217 else
218 if (buffering) {
219 qDebug("MPVProcess::parseLine: buffering");
220 receivedBuffering();
221 return;
222 }
223 else
224 if (idle) {
225 qDebug("MPVProcess::parseLine: idle");
226 receivedBuffering();
227 return;
228 }
229 notified_pause = false;
230
231 #else
232
233 //qDebug() << rx_mpv_av.cap(1);
234 //qDebug() << rx_mpv_av.cap(2);
235
236 QString status = rx_mpv_av.cap(2).trimmed();
237
238 int i = 4;
239 int h = rx_mpv_av.cap(i++).toInt();
240 int m = rx_mpv_av.cap(i++).toInt();
241 int s = rx_mpv_av.cap(i++).toInt();
242 //qDebug("%d:%d:%d", h, m, s);
243 double sec = h * 3600 + m * 60 + s;
244
245 h = rx_mpv_av.cap(i++).toInt();
246 m = rx_mpv_av.cap(i++).toInt();
247 s = rx_mpv_av.cap(i++).toInt();
248 double length = h * 3600 + m * 60 + s;
249 if (length != md.duration) {
250 md.duration = length;
251 emit receivedDuration(length);
252 }
253
254 if (status == "Paused") {
255 receivedPause();
256 return;
257 }
258 else
259 if ((status == "...") || (status == "Buffering")) {
260 receivedBuffering();
261 return;
262 }
263
264 if (!status.isEmpty()) {
265 qDebug() << "MPVProcess::parseLine: status:" << status;
266 }
267
268 #endif
269
270#if NOTIFY_SUB_CHANGES
271 if (notified_mplayer_is_running) {
272 if (subtitle_info_changed) {
273 qDebug("MPVProcess::parseLine: subtitle_info_changed");
274 subtitle_info_changed = false;
275 subtitle_info_received = false;
276 emit subtitleInfoChanged(subs);
277 }
278 if (subtitle_info_received) {
279 qDebug("MPVProcess::parseLine: subtitle_info_received");
280 subtitle_info_received = false;
281 emit subtitleInfoReceivedAgain(subs);
282 }
283 }
284#endif
285
286#if NOTIFY_AUDIO_CHANGES
287 if (notified_mplayer_is_running) {
288 if (audio_info_changed) {
289 qDebug("MPVProcess::parseLine: audio_info_changed");
290 audio_info_changed = false;
291 emit audioInfoChanged(audios);
292 }
293 }
294#endif
295
296#if NOTIFY_VIDEO_CHANGES
297 if (notified_mplayer_is_running) {
298 if (video_info_changed) {
299 qDebug("MPVProcess::parseLine: video_info_changed");
300 video_info_changed = false;
301 emit videoInfoChanged(videos);
302 }
303 }
304#endif
305
306#if NOTIFY_CHAPTER_CHANGES
307 if (notified_mplayer_is_running) {
308 if (chapter_info_changed) {
309 qDebug("MPVProcess::parseLine: chapter_info_changed");
310 chapter_info_changed = false;
311 emit chaptersChanged(chapters);
312 }
313 }
314#endif
315
316 if (!notified_mplayer_is_running) {
317 qDebug("MPVProcess::parseLine: starting sec: %f", sec);
318
319 if (md.video_width == 0 || md.video_height == 0) {
320 md.novideo = true;
321 emit receivedNoVideo();
322 }
323
324 /*
325 if ( (md.n_chapters <= 0) && (dvd_current_title > 0) &&
326 (md.titles.find(dvd_current_title) != -1) )
327 {
328 int idx = md.titles.find(dvd_current_title);
329 md.n_chapters = md.titles.itemAt(idx).chapters();
330 qDebug("MPVProcess::parseLine: setting chapters to %d", md.n_chapters);
331 }
332 */
333
334 /*
335 #if CHECK_VIDEO_CODEC_FOR_NO_VIDEO
336 // Another way to find out if there's no video
337 if (md.video_codec.isEmpty()) {
338 md.novideo = true;
339 emit receivedNoVideo();
340 }
341 #endif
342 */
343
344 emit receivedStartingTime(sec);
345 emit mplayerFullyLoaded();
346
347 emit receivedCurrentFrame(0); // Ugly hack: set the frame counter to 0
348
349 notified_mplayer_is_running = true;
350
351 // Wait some secs to ask for bitrate
352 QTimer::singleShot(12000, this, SLOT(requestBitrateInfo()));
353 }
354
355 emit receivedCurrentSec( sec );
356 }
357 else {
358 emit lineAvailable(line);
359
360 // Parse other things
361 qDebug("MPVProcess::parseLine: '%s'", line.toUtf8().data() );
362
363 // End of file
364 if (rx_mpv_endoffile.indexIn(line) > -1) {
365 qDebug("MVPProcess::parseLine: detected end of file");
366 if (!received_end_of_file) {
367 // In case of playing VCDs or DVDs, maybe the first title
368 // is not playable, so the GUI doesn't get the info about
369 // available titles. So if we received the end of file
370 // first let's pretend the file has started so the GUI can have
371 // the data.
372 if ( !notified_mplayer_is_running) {
373 emit mplayerFullyLoaded();
374 }
375 // Send signal once the process is finished, not now!
376 received_end_of_file = true;
377 }
378 }
379 else
380
381 // Window resolution
382 if (rx_mpv_dsize.indexIn(line) > -1) {
383 int w = rx_mpv_dsize.cap(1).toInt();
384 int h = rx_mpv_dsize.cap(2).toInt();
385 emit receivedWindowResolution( w, h );
386 }
387 else
388
389 // VO
390 if (rx_mpv_vo.indexIn(line) > -1) {
391 emit receivedVO( rx_mpv_vo.cap(1) );
392 // Ask for window resolution
393 writeToStdin("print_text INFO_VIDEO_DSIZE=${=dwidth}x${=dheight}");
394 }
395 else
396
397 // AO
398 if (rx_mpv_ao.indexIn(line) > -1) {
399 emit receivedAO( rx_mpv_ao.cap(1) );
400 }
401 else
402
403
404 // Audio
405 if (rx_mpv_audio.indexIn(line) > -1) {
406 int ID = rx_mpv_audio.cap(1).toInt();
407 QString lang = rx_mpv_audio.cap(3);
408 QString title = rx_mpv_audio.cap(6);
409 qDebug("MPVProcess::parseLine: audio id: %d, lang: '%s', name: '%s'", ID, lang.toUtf8().constData(), title.toUtf8().constData());
410
411 #if NOTIFY_AUDIO_CHANGES
412 updateAudioTrack(ID, title, lang);
413 #else
414 if (md.audios.find(ID) == -1) {
415 md.audios.addID(ID);
416 md.audios.addName(ID, title);
417 md.audios.addLang(ID, lang);
418 }
419 #endif
420 }
421 else
422
423 if (rx_mpv_stream_title.indexIn(line) > -1) {
424 QString s = rx_mpv_stream_title.cap(1);
425 qDebug("MPVProcess::parseLine: stream_title: '%s'", s.toUtf8().data());
426 md.stream_title = s;
427 emit receivedStreamTitle(s);
428 }
429 else
430
431 // Subtitles
432 if (rx_mpv_subs.indexIn(line) > -1) {
433 int ID = rx_mpv_subs.cap(1).toInt();
434 QString lang = rx_mpv_subs.cap(3);
435 QString title = rx_mpv_subs.cap(6);
436 qDebug("MPVProcess::parseLine: sub id: %d, lang: '%s', name: '%s'", ID, lang.toUtf8().constData(), title.toUtf8().constData());
437
438 #if NOTIFY_SUB_CHANGES
439 updateSubtitleTrack(ID, title, lang);
440 #else
441 if (md.subs.find(SubData::Sub, ID) == -1) {
442 md.subs.add(SubData::Sub, ID);
443 md.subs.changeName(SubData::Sub, ID, title);
444 md.subs.changeLang(SubData::Sub, ID, lang);
445 }
446 #endif
447 }
448 else
449 #if 0
450 if (rx_mpv_subs2.indexIn(line) > -1) {
451 bool selected = (rx_mpv_subs2.cap(1) == " >");
452 int ID = rx_mpv_subs2.cap(2).toInt();
453 QString title = rx_mpv_subs2.cap(3);
454 qDebug("MPVProcess::parseLine: sub id: %d title: '%s' selected: %d", ID, title.toUtf8().constData(), selected);
455 if (md.subs.find(SubData::Sub, ID) == -1) {
456 md.subs.add(SubData::Sub, ID);
457 md.subs.changeName(SubData::Sub, ID, title);
458 }
459 }
460 else
461 #endif
462
463#if !NOTIFY_VIDEO_CHANGES
464 // Video
465 if (rx_mpv_video.indexIn(line) > -1) {
466 int ID = rx_mpv_video.cap(1).toInt();
467 QString title = rx_mpv_video.cap(4);
468 qDebug("MPVProcess::parseLine: video id: %d, name: '%s'", ID, title.toUtf8().constData());
469 //md.videos.addID(ID);
470 md.videos.addName(ID, title);
471 }
472 else
473#endif
474
475#if 0
476 // Video info
477 if (rx_mpv_videoinfo.indexIn(line) > -1) {
478 md.video_width = rx_mpv_videoinfo.cap(1).toInt();
479 md.video_height = rx_mpv_videoinfo.cap(2).toInt();
480 md.video_fps = rx_mpv_videoinfo.cap(3);
481 qDebug("MPVProcess::parseLine: width: %d height: %d fps: %s", md.video_width, md.video_height, md.video_fps.toUtf8().constData());
482 }
483 else
484#endif
485
486 // Chapters
487 if (rx_mpv_chaptername.indexIn(line) > -1) {
488 int ID = rx_mpv_chaptername.cap(1).toInt();
489 QString title = rx_mpv_chaptername.cap(2);
490 if (title.isEmpty()) title = QString::number(ID + 1);
491 #if NOTIFY_CHAPTER_CHANGES
492 chapters.addName(ID, title);
493 chapter_info_changed = true;
494 #else
495 md.chapters.addName(ID, title);
496 #endif
497 qDebug("MPVProcess::parseLine: chapter id: %d title: %s", ID, title.toUtf8().constData());
498 //md.chapters.list();
499 }
500 else
501
502#if NOTIFY_VIDEO_CHANGES || NOTIFY_AUDIO_CHANGES || NOTIFY_SUB_CHANGES
503 // Track info
504 if (rx_mpv_trackinfo.indexIn(line) > -1) {
505 int ID = rx_mpv_trackinfo.cap(3).toInt();
506 QString type = rx_mpv_trackinfo.cap(2);
507 QString name = rx_mpv_trackinfo.cap(5);
508 QString lang = rx_mpv_trackinfo.cap(4);
509 QString selected = rx_mpv_trackinfo.cap(6);
510 qDebug("MPVProcess::parseLine: ID: %d type: %s name: %s lang: %s selected: %s", ID, type.toUtf8().constData(),
511 name.toUtf8().constData(), lang.toUtf8().constData(), selected.toUtf8().constData());
512 /*
513 if (lang == "(unavailable)") lang = "";
514 if (name == "(unavailable)") name = "";
515 */
516 if (type == "video") {
517 #if NOTIFY_VIDEO_CHANGES
518 int idx = videos.find(ID);
519 if (idx == -1) {
520 video_info_changed = true;
521 videos.addName(ID, name);
522 videos.addLang(ID, lang);
523 } else {
524 // Track already existed
525 if (videos.itemAt(idx).name() != name) {
526 video_info_changed = true;
527 videos.addName(ID, name);
528 }
529 if (videos.itemAt(idx).lang() != lang) {
530 video_info_changed = true;
531 videos.addLang(ID, lang);
532 }
533 }
534 #endif
535 }
536 else
537 if (type == "audio") {
538 #if NOTIFY_AUDIO_CHANGES
539 updateAudioTrack(ID, name, lang);
540 #endif
541 }
542 else
543 if (type == "sub") {
544 #if NOTIFY_SUB_CHANGES
545 updateSubtitleTrack(ID, name, lang);
546 #endif
547 }
548 }
549 else
550#endif
551
552#if DVDNAV_SUPPORT
553 if (rx_mpv_switch_title.indexIn(line) > -1) {
554 int title = rx_mpv_switch_title.cap(1).toInt();
555 qDebug("MPVProcess::parseLine: title changed to %d", title);
556 // Ask for track info
557 // Wait 10 secs. because it can take a while until the title start to play
558 QTimer::singleShot(10000, this, SLOT(requestChapterInfo()));
559 }
560 else
561#endif
562
563 //Playing
564 if (rx_mpv_playing.indexIn(line) > -1) {
565 emit receivedPlaying();
566 }
567 else
568
569 if (rx_mpv_videocodec.indexIn(line) > -1) {
570 md.video_codec = rx_mpv_videocodec.cap(2);
571 qDebug("MPVProcess::parseLine: md.video_codec '%s'", md.video_codec.toUtf8().constData());
572 }
573 else
574 if (rx_mpv_audiocodec.indexIn(line) > -1) {
575 md.audio_codec = rx_mpv_audiocodec.cap(2);
576 qDebug("MPVProcess::parseLine: md.audio_codec '%s'", md.audio_codec.toUtf8().constData());
577 }
578 else
579
580 if (rx_mpv_forbidden.indexIn(line) > -1) {
581 qDebug("MVPProcess::parseLine: 403 forbidden");
582 emit receivedForbiddenText();
583 }
584
585 //Generic things
586 if (rx_mpv_generic.indexIn(line) > -1) {
587 tag = rx_mpv_generic.cap(1);
588 value = rx_mpv_generic.cap(2);
589 //qDebug("MPVProcess::parseLine: tag: %s", tag.toUtf8().constData());
590 //qDebug("MPVProcess::parseLine: value: %s", value.toUtf8().constData());
591
592 if (tag == "INFO_VIDEO_WIDTH") {
593 md.video_width = value.toInt();
594 qDebug("MPVProcess::parseLine: md.video_width set to %d", md.video_width);
595 }
596 else
597 if (tag == "INFO_VIDEO_HEIGHT") {
598 md.video_height = value.toInt();
599 qDebug("MPVProcess::parseLine: md.video_height set to %d", md.video_height);
600 }
601 else
602 if (tag == "INFO_VIDEO_ASPECT") {
603 md.video_aspect = value.toDouble();
604 if ( md.video_aspect == 0.0 ) {
605 // I hope width & height are already set.
606 md.video_aspect = (double) md.video_width / md.video_height;
607 }
608 qDebug("MPVProcess::parseLine: md.video_aspect set to %f", md.video_aspect);
609 }
610 if (tag == "INFO_VIDEO_BITRATE") {
611 int bitrate = value.toInt();
612 emit receivedVideoBitrate(bitrate);
613 }
614 else
615 if (tag == "INFO_LENGTH") {
616 md.duration = value.toDouble();
617 qDebug("MPVProcess::parseLine: md.duration set to %f", md.duration);
618 }
619 else
620 if (tag == "INFO_DEMUXER") {
621 md.demuxer = value;
622 }
623 else
624 if (tag == "INFO_VIDEO_FORMAT") {
625 md.video_format = value;
626 }
627 if (tag == "INFO_VIDEO_FPS") {
628 md.video_fps = value;
629 }
630 else
631 /*
632 if (tag == "INFO_VIDEO_CODEC") {
633 md.video_codec = value;
634 }
635 else
636 if (tag == "INFO_AUDIO_CODEC") {
637 md.audio_codec = value;
638 }
639 else
640 */
641 if (tag == "INFO_AUDIO_BITRATE") {
642 int bitrate = value.toInt();
643 emit receivedAudioBitrate(bitrate);
644 }
645 else
646 if (tag == "INFO_AUDIO_RATE") {
647 md.audio_rate = value.toInt();
648 }
649 else
650 if (tag == "INFO_AUDIO_NCH") {
651 md.audio_nch = value.toInt();
652 }
653 else
654 if (tag == "INFO_AUDIO_FORMAT") {
655 md.audio_format = value;
656 }
657 else
658 if (tag == "INFO_CHAPTERS") {
659 md.n_chapters = value.toInt();
660 #ifdef TOO_CHAPTERS_WORKAROUND
661 if (md.n_chapters > 1000) {
662 qDebug("MPVProcess::parseLine: warning too many chapters: %d", md.n_chapters);
663 qDebug(" chapters will be ignored");
664 md.n_chapters = 0;
665 }
666 #endif
667 for (int n = 0; n < md.n_chapters; n++) {
668 writeToStdin(QString("print_text INFO_CHAPTER_%1_NAME=${chapter-list/%1/title}").arg(n));
669 }
670 }
671 else
672 if (tag == "INFO_TITLES") {
673 int n_titles = value.toInt();
674 for (int ID = 0; ID < n_titles; ID++) {
675 md.titles.addName(ID, QString::number(ID+1));
676 }
677 }
678 else
679 if (tag == "METADATA_TITLE") {
680 if (!value.isEmpty()) md.clip_name = value;
681 }
682 else
683 if (tag == "METADATA_ARTIST") {
684 if (!value.isEmpty()) md.clip_artist = value;
685 }
686 else
687 if (tag == "METADATA_DATE") {
688 if (!value.isEmpty()) md.clip_date = value;
689 }
690 else
691 if (tag == "METADATA_ALBUM") {
692 if (!value.isEmpty()) md.clip_album = value;
693 }
694 else
695 if (tag == "METADATA_COPYRIGHT") {
696 if (!value.isEmpty()) md.clip_copyright = value;
697 }
698 else
699 if (tag == "METADATA_TRACK") {
700 if (!value.isEmpty()) md.clip_track = value;
701 }
702 else
703 if (tag == "METADATA_GENRE") {
704 if (!value.isEmpty()) md.clip_genre = value;
705 }
706 else
707 if (tag == "INFO_MEDIA_TITLE") {
708 if (!value.isEmpty() && value != "mp4" && !value.startsWith("mp4&") /*&& md.clip_name.isEmpty()*/) {
709 md.clip_name = value;
710 }
711 }
712 else
713 if (tag == "MPV_VERSION") {
714 mpv_version = value;
715 //qDebug("MPVProcess::parseLine: mpv version: %s", mpv_version.toUtf8().constData());
716 }
717#if NOTIFY_VIDEO_CHANGES || NOTIFY_AUDIO_CHANGES || NOTIFY_SUB_CHANGES
718 else
719 if (tag == "INFO_TRACKS_COUNT") {
720 int tracks = value.toInt();
721 for (int n = 0; n < tracks; n++) {
722 writeToStdin(QString("print_text \"INFO_TRACK_%1: "
723 "${track-list/%1/type} "
724 "${track-list/%1/id} "
725 "'${track-list/%1/lang:}' "
726 "'${track-list/%1/title:}' "
727 "${track-list/%1/selected}\"").arg(n));
728 }
729 }
730#endif
731 }
732 }
733}
734
735void MPVProcess::requestChapterInfo() {
736 writeToStdin("print_text \"INFO_CHAPTERS=${=chapters}\"");
737}
738
739void MPVProcess::requestBitrateInfo() {
740 writeToStdin("print_text INFO_VIDEO_BITRATE=${=video-bitrate}");
741 writeToStdin("print_text INFO_AUDIO_BITRATE=${=audio-bitrate}");
742}
743
744#if NOTIFY_AUDIO_CHANGES
745void MPVProcess::updateAudioTrack(int ID, const QString & name, const QString & lang) {
746 qDebug("MPVProcess::updateAudioTrack: ID: %d", ID);
747
748 int idx = audios.find(ID);
749 if (idx == -1) {
750 audio_info_changed = true;
751 audios.addName(ID, name);
752 audios.addLang(ID, lang);
753 } else {
754 // Track already existed
755 if (audios.itemAt(idx).name() != name) {
756 audio_info_changed = true;
757 audios.addName(ID, name);
758 }
759 if (audios.itemAt(idx).lang() != lang) {
760 audio_info_changed = true;
761 audios.addLang(ID, lang);
762 }
763 }
764}
765#endif
766
767#if NOTIFY_SUB_CHANGES
768void MPVProcess::updateSubtitleTrack(int ID, const QString & name, const QString & lang) {
769 qDebug("MPVProcess::updateSubtitleTrack: ID: %d", ID);
770
771 int idx = subs.find(SubData::Sub, ID);
772 if (idx == -1) {
773 subtitle_info_changed = true;
774 subs.add(SubData::Sub, ID);
775 subs.changeName(SubData::Sub, ID, name);
776 subs.changeLang(SubData::Sub, ID, lang);
777 }
778 else {
779 // Track already existed
780 if (subs.itemAt(idx).name() != name) {
781 subtitle_info_changed = true;
782 subs.changeName(SubData::Sub, ID, name);
783 }
784 if (subs.itemAt(idx).lang() != lang) {
785 subtitle_info_changed = true;
786 subs.changeLang(SubData::Sub, ID, lang);
787 }
788 }
789}
790#endif
791
792// Called when the process is finished
793void MPVProcess::processFinished(int exitCode, QProcess::ExitStatus exitStatus) {
794 qDebug("MPVProcess::processFinished: exitCode: %d, status: %d", exitCode, (int) exitStatus);
795 // Send this signal before the endoffile one, otherwise
796 // the playlist will start to play next file before all
797 // objects are notified that the process has exited.
798 emit processExited();
799 if (received_end_of_file) emit receivedEndOfFile();
800}
801
802void MPVProcess::gotError(QProcess::ProcessError error) {
803 qDebug("MPVProcess::gotError: %d", (int) error);
804}
805
806#include "mpvoptions.cpp"
807#include "moc_mpvprocess.cpp"
Note: See TracBrowser for help on using the repository browser.