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

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

smplayer: update trunk to version 16.8.0

File size: 22.0 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 static double last_sec = -1;
193
194 // Parse A: V: line
195 //qDebug("MPVProcess::parseLine: %s", line.toUtf8().data());
196 if (rx_mpv_av.indexIn(line) > -1) {
197 #ifdef CUSTOM_STATUS
198 double sec = rx_mpv_av.cap(1).toDouble();
199 double length = rx_mpv_av.cap(2).toDouble();
200 bool paused = (rx_mpv_av.cap(3) == "yes");
201 bool buffering = (rx_mpv_av.cap(4) == "yes");
202 bool idle = (rx_mpv_av.cap(5) == "yes");
203
204 if (length != md.duration) {
205 md.duration = length;
206 #if DVDNAV_SUPPORT
207 emit receivedDuration(length);
208 #endif
209 }
210
211 if (paused && notified_pause) {
212 if (last_sec != sec) {
213 last_sec = sec;
214 emit receivedCurrentSec(sec);
215 emit receivedPause();
216 }
217 return;
218 }
219
220 if (paused) {
221 notified_pause = true;
222 qDebug("MPVProcess::parseLine: paused");
223 emit receivedPause();
224 return;
225 }
226 else
227 if (buffering) {
228 qDebug("MPVProcess::parseLine: buffering");
229 emit receivedBuffering();
230 return;
231 }
232 else
233 if (idle) {
234 qDebug("MPVProcess::parseLine: idle");
235 emit receivedBuffering();
236 return;
237 }
238 notified_pause = false;
239
240 #else
241
242 //qDebug() << rx_mpv_av.cap(1);
243 //qDebug() << rx_mpv_av.cap(2);
244
245 QString status = rx_mpv_av.cap(2).trimmed();
246
247 int i = 4;
248 int h = rx_mpv_av.cap(i++).toInt();
249 int m = rx_mpv_av.cap(i++).toInt();
250 int s = rx_mpv_av.cap(i++).toInt();
251 //qDebug("%d:%d:%d", h, m, s);
252 double sec = h * 3600 + m * 60 + s;
253
254 h = rx_mpv_av.cap(i++).toInt();
255 m = rx_mpv_av.cap(i++).toInt();
256 s = rx_mpv_av.cap(i++).toInt();
257 double length = h * 3600 + m * 60 + s;
258 if (length != md.duration) {
259 md.duration = length;
260 emit receivedDuration(length);
261 }
262
263 if (status == "Paused") {
264 emit receivedPause();
265 return;
266 }
267 else
268 if ((status == "...") || (status == "Buffering")) {
269 emit receivedBuffering();
270 return;
271 }
272
273 if (!status.isEmpty()) {
274 qDebug() << "MPVProcess::parseLine: status:" << status;
275 }
276
277 #endif
278
279#if NOTIFY_SUB_CHANGES
280 if (notified_mplayer_is_running) {
281 if (subtitle_info_changed) {
282 qDebug("MPVProcess::parseLine: subtitle_info_changed");
283 subtitle_info_changed = false;
284 subtitle_info_received = false;
285 emit subtitleInfoChanged(subs);
286 }
287 if (subtitle_info_received) {
288 qDebug("MPVProcess::parseLine: subtitle_info_received");
289 subtitle_info_received = false;
290 emit subtitleInfoReceivedAgain(subs);
291 }
292 }
293#endif
294
295#if NOTIFY_AUDIO_CHANGES
296 if (notified_mplayer_is_running) {
297 if (audio_info_changed) {
298 qDebug("MPVProcess::parseLine: audio_info_changed");
299 audio_info_changed = false;
300 emit audioInfoChanged(audios);
301 }
302 }
303#endif
304
305#if NOTIFY_VIDEO_CHANGES
306 if (notified_mplayer_is_running) {
307 if (video_info_changed) {
308 qDebug("MPVProcess::parseLine: video_info_changed");
309 video_info_changed = false;
310 emit videoInfoChanged(videos);
311 }
312 }
313#endif
314
315#if NOTIFY_CHAPTER_CHANGES
316 if (notified_mplayer_is_running) {
317 if (chapter_info_changed) {
318 qDebug("MPVProcess::parseLine: chapter_info_changed");
319 chapter_info_changed = false;
320 emit chaptersChanged(chapters);
321 }
322 }
323#endif
324
325 if (!notified_mplayer_is_running) {
326 qDebug("MPVProcess::parseLine: starting sec: %f", sec);
327
328 if (md.video_width == 0 || md.video_height == 0) {
329 md.novideo = true;
330 emit receivedNoVideo();
331 }
332
333 /*
334 if ( (md.n_chapters <= 0) && (dvd_current_title > 0) &&
335 (md.titles.find(dvd_current_title) != -1) )
336 {
337 int idx = md.titles.find(dvd_current_title);
338 md.n_chapters = md.titles.itemAt(idx).chapters();
339 qDebug("MPVProcess::parseLine: setting chapters to %d", md.n_chapters);
340 }
341 */
342
343 /*
344 #if CHECK_VIDEO_CODEC_FOR_NO_VIDEO
345 // Another way to find out if there's no video
346 if (md.video_codec.isEmpty()) {
347 md.novideo = true;
348 emit receivedNoVideo();
349 }
350 #endif
351 */
352
353 emit receivedStartingTime(sec);
354 emit mplayerFullyLoaded();
355
356 emit receivedCurrentFrame(0); // Ugly hack: set the frame counter to 0
357
358 notified_mplayer_is_running = true;
359
360 // Wait some secs to ask for bitrate
361 QTimer::singleShot(12000, this, SLOT(requestBitrateInfo()));
362 }
363
364 emit receivedCurrentSec( sec );
365 }
366 else {
367 emit lineAvailable(line);
368
369 // Parse other things
370 qDebug("MPVProcess::parseLine: '%s'", line.toUtf8().data() );
371
372 // End of file
373 if (rx_mpv_endoffile.indexIn(line) > -1) {
374 qDebug("MVPProcess::parseLine: detected end of file");
375 if (!received_end_of_file) {
376 // In case of playing VCDs or DVDs, maybe the first title
377 // is not playable, so the GUI doesn't get the info about
378 // available titles. So if we received the end of file
379 // first let's pretend the file has started so the GUI can have
380 // the data.
381 if ( !notified_mplayer_is_running) {
382 emit mplayerFullyLoaded();
383 }
384 // Send signal once the process is finished, not now!
385 received_end_of_file = true;
386 }
387 }
388 else
389
390 // Window resolution
391 if (rx_mpv_dsize.indexIn(line) > -1) {
392 int w = rx_mpv_dsize.cap(1).toInt();
393 int h = rx_mpv_dsize.cap(2).toInt();
394 emit receivedWindowResolution( w, h );
395 }
396 else
397
398 // VO
399 if (rx_mpv_vo.indexIn(line) > -1) {
400 emit receivedVO( rx_mpv_vo.cap(1) );
401 // Ask for window resolution
402 writeToStdin("print_text INFO_VIDEO_DSIZE=${=dwidth}x${=dheight}");
403 }
404 else
405
406 // AO
407 if (rx_mpv_ao.indexIn(line) > -1) {
408 emit receivedAO( rx_mpv_ao.cap(1) );
409 }
410 else
411
412
413 // Audio
414 if (rx_mpv_audio.indexIn(line) > -1) {
415 int ID = rx_mpv_audio.cap(1).toInt();
416 QString lang = rx_mpv_audio.cap(3);
417 QString title = rx_mpv_audio.cap(6);
418 qDebug("MPVProcess::parseLine: audio id: %d, lang: '%s', name: '%s'", ID, lang.toUtf8().constData(), title.toUtf8().constData());
419
420 #if NOTIFY_AUDIO_CHANGES
421 updateAudioTrack(ID, title, lang);
422 #else
423 if (md.audios.find(ID) == -1) {
424 md.audios.addID(ID);
425 md.audios.addName(ID, title);
426 md.audios.addLang(ID, lang);
427 }
428 #endif
429 }
430 else
431
432 if (rx_mpv_stream_title.indexIn(line) > -1) {
433 QString s = rx_mpv_stream_title.cap(1);
434 qDebug("MPVProcess::parseLine: stream_title: '%s'", s.toUtf8().data());
435 md.stream_title = s;
436 emit receivedStreamTitle(s);
437 }
438 else
439
440 // Subtitles
441 if (rx_mpv_subs.indexIn(line) > -1) {
442 int ID = rx_mpv_subs.cap(1).toInt();
443 QString lang = rx_mpv_subs.cap(3);
444 QString title = rx_mpv_subs.cap(6);
445 qDebug("MPVProcess::parseLine: sub id: %d, lang: '%s', name: '%s'", ID, lang.toUtf8().constData(), title.toUtf8().constData());
446
447 #if NOTIFY_SUB_CHANGES
448 updateSubtitleTrack(ID, title, lang);
449 #else
450 if (md.subs.find(SubData::Sub, ID) == -1) {
451 md.subs.add(SubData::Sub, ID);
452 md.subs.changeName(SubData::Sub, ID, title);
453 md.subs.changeLang(SubData::Sub, ID, lang);
454 }
455 #endif
456 }
457 else
458 #if 0
459 if (rx_mpv_subs2.indexIn(line) > -1) {
460 bool selected = (rx_mpv_subs2.cap(1) == " >");
461 int ID = rx_mpv_subs2.cap(2).toInt();
462 QString title = rx_mpv_subs2.cap(3);
463 qDebug("MPVProcess::parseLine: sub id: %d title: '%s' selected: %d", ID, title.toUtf8().constData(), selected);
464 if (md.subs.find(SubData::Sub, ID) == -1) {
465 md.subs.add(SubData::Sub, ID);
466 md.subs.changeName(SubData::Sub, ID, title);
467 }
468 }
469 else
470 #endif
471
472#if !NOTIFY_VIDEO_CHANGES
473 // Video
474 if (rx_mpv_video.indexIn(line) > -1) {
475 int ID = rx_mpv_video.cap(1).toInt();
476 QString title = rx_mpv_video.cap(4);
477 qDebug("MPVProcess::parseLine: video id: %d, name: '%s'", ID, title.toUtf8().constData());
478 //md.videos.addID(ID);
479 md.videos.addName(ID, title);
480 }
481 else
482#endif
483
484#if 0
485 // Video info
486 if (rx_mpv_videoinfo.indexIn(line) > -1) {
487 md.video_width = rx_mpv_videoinfo.cap(1).toInt();
488 md.video_height = rx_mpv_videoinfo.cap(2).toInt();
489 md.video_fps = rx_mpv_videoinfo.cap(3);
490 qDebug("MPVProcess::parseLine: width: %d height: %d fps: %s", md.video_width, md.video_height, md.video_fps.toUtf8().constData());
491 }
492 else
493#endif
494
495 // Chapters
496 if (rx_mpv_chaptername.indexIn(line) > -1) {
497 int ID = rx_mpv_chaptername.cap(1).toInt();
498 QString title = rx_mpv_chaptername.cap(2);
499 if (title.isEmpty()) title = QString::number(ID + 1);
500 #if NOTIFY_CHAPTER_CHANGES
501 chapters.addName(ID, title);
502 chapter_info_changed = true;
503 #else
504 md.chapters.addName(ID, title);
505 #endif
506 qDebug("MPVProcess::parseLine: chapter id: %d title: %s", ID, title.toUtf8().constData());
507 //md.chapters.list();
508 }
509 else
510
511#if NOTIFY_VIDEO_CHANGES || NOTIFY_AUDIO_CHANGES || NOTIFY_SUB_CHANGES
512 // Track info
513 if (rx_mpv_trackinfo.indexIn(line) > -1) {
514 int ID = rx_mpv_trackinfo.cap(3).toInt();
515 QString type = rx_mpv_trackinfo.cap(2);
516 QString name = rx_mpv_trackinfo.cap(5);
517 QString lang = rx_mpv_trackinfo.cap(4);
518 QString selected = rx_mpv_trackinfo.cap(6);
519 qDebug("MPVProcess::parseLine: ID: %d type: %s name: %s lang: %s selected: %s", ID, type.toUtf8().constData(),
520 name.toUtf8().constData(), lang.toUtf8().constData(), selected.toUtf8().constData());
521 /*
522 if (lang == "(unavailable)") lang = "";
523 if (name == "(unavailable)") name = "";
524 */
525 if (type == "video") {
526 #if NOTIFY_VIDEO_CHANGES
527 int idx = videos.find(ID);
528 if (idx == -1) {
529 video_info_changed = true;
530 videos.addName(ID, name);
531 videos.addLang(ID, lang);
532 } else {
533 // Track already existed
534 if (videos.itemAt(idx).name() != name) {
535 video_info_changed = true;
536 videos.addName(ID, name);
537 }
538 if (videos.itemAt(idx).lang() != lang) {
539 video_info_changed = true;
540 videos.addLang(ID, lang);
541 }
542 }
543 #endif
544 }
545 else
546 if (type == "audio") {
547 #if NOTIFY_AUDIO_CHANGES
548 updateAudioTrack(ID, name, lang);
549 #endif
550 }
551 else
552 if (type == "sub") {
553 #if NOTIFY_SUB_CHANGES
554 updateSubtitleTrack(ID, name, lang);
555 #endif
556 }
557 }
558 else
559#endif
560
561#if DVDNAV_SUPPORT
562 if (rx_mpv_switch_title.indexIn(line) > -1) {
563 int title = rx_mpv_switch_title.cap(1).toInt();
564 qDebug("MPVProcess::parseLine: title changed to %d", title);
565 // Ask for track info
566 // Wait 10 secs. because it can take a while until the title start to play
567 QTimer::singleShot(10000, this, SLOT(requestChapterInfo()));
568 }
569 else
570#endif
571
572 //Playing
573 if (rx_mpv_playing.indexIn(line) > -1) {
574 emit receivedPlaying();
575 }
576 else
577
578 if (rx_mpv_videocodec.indexIn(line) > -1) {
579 md.video_codec = rx_mpv_videocodec.cap(2);
580 qDebug("MPVProcess::parseLine: md.video_codec '%s'", md.video_codec.toUtf8().constData());
581 }
582 else
583 if (rx_mpv_audiocodec.indexIn(line) > -1) {
584 md.audio_codec = rx_mpv_audiocodec.cap(2);
585 qDebug("MPVProcess::parseLine: md.audio_codec '%s'", md.audio_codec.toUtf8().constData());
586 }
587 else
588
589 if (rx_mpv_forbidden.indexIn(line) > -1) {
590 qDebug("MVPProcess::parseLine: 403 forbidden");
591 emit receivedForbiddenText();
592 }
593
594 //Generic things
595 if (rx_mpv_generic.indexIn(line) > -1) {
596 tag = rx_mpv_generic.cap(1);
597 value = rx_mpv_generic.cap(2);
598 //qDebug("MPVProcess::parseLine: tag: %s", tag.toUtf8().constData());
599 //qDebug("MPVProcess::parseLine: value: %s", value.toUtf8().constData());
600
601 if (tag == "INFO_VIDEO_WIDTH") {
602 md.video_width = value.toInt();
603 qDebug("MPVProcess::parseLine: md.video_width set to %d", md.video_width);
604 }
605 else
606 if (tag == "INFO_VIDEO_HEIGHT") {
607 md.video_height = value.toInt();
608 qDebug("MPVProcess::parseLine: md.video_height set to %d", md.video_height);
609 }
610 else
611 if (tag == "INFO_VIDEO_ASPECT") {
612 md.video_aspect = value.toDouble();
613 if ( md.video_aspect == 0.0 ) {
614 // I hope width & height are already set.
615 md.video_aspect = (double) md.video_width / md.video_height;
616 }
617 qDebug("MPVProcess::parseLine: md.video_aspect set to %f", md.video_aspect);
618 }
619 if (tag == "INFO_VIDEO_BITRATE") {
620 int bitrate = value.toInt();
621 emit receivedVideoBitrate(bitrate);
622 }
623 else
624 if (tag == "INFO_LENGTH") {
625 md.duration = value.toDouble();
626 qDebug("MPVProcess::parseLine: md.duration set to %f", md.duration);
627 }
628 else
629 if (tag == "INFO_DEMUXER") {
630 md.demuxer = value;
631 }
632 else
633 if (tag == "INFO_VIDEO_FORMAT") {
634 md.video_format = value;
635 }
636 if (tag == "INFO_VIDEO_FPS") {
637 md.video_fps = value;
638 }
639 else
640 /*
641 if (tag == "INFO_VIDEO_CODEC") {
642 md.video_codec = value;
643 }
644 else
645 if (tag == "INFO_AUDIO_CODEC") {
646 md.audio_codec = value;
647 }
648 else
649 */
650 if (tag == "INFO_AUDIO_BITRATE") {
651 int bitrate = value.toInt();
652 emit receivedAudioBitrate(bitrate);
653 }
654 else
655 if (tag == "INFO_AUDIO_RATE") {
656 md.audio_rate = value.toInt();
657 }
658 else
659 if (tag == "INFO_AUDIO_NCH") {
660 md.audio_nch = value.toInt();
661 }
662 else
663 if (tag == "INFO_AUDIO_FORMAT") {
664 md.audio_format = value;
665 }
666 else
667 if (tag == "INFO_CHAPTERS") {
668 md.n_chapters = value.toInt();
669 #ifdef TOO_CHAPTERS_WORKAROUND
670 if (md.n_chapters > 1000) {
671 qDebug("MPVProcess::parseLine: warning too many chapters: %d", md.n_chapters);
672 qDebug(" chapters will be ignored");
673 md.n_chapters = 0;
674 }
675 #endif
676 for (int n = 0; n < md.n_chapters; n++) {
677 writeToStdin(QString("print_text INFO_CHAPTER_%1_NAME=${chapter-list/%1/title}").arg(n));
678 }
679 }
680 else
681 if (tag == "INFO_TITLES") {
682 int n_titles = value.toInt();
683 for (int ID = 0; ID < n_titles; ID++) {
684 md.titles.addName(ID, QString::number(ID+1));
685 }
686 }
687 else
688 if (tag == "METADATA_TITLE") {
689 if (!value.isEmpty()) md.clip_name = value;
690 }
691 else
692 if (tag == "METADATA_ARTIST") {
693 if (!value.isEmpty()) md.clip_artist = value;
694 }
695 else
696 if (tag == "METADATA_DATE") {
697 if (!value.isEmpty()) md.clip_date = value;
698 }
699 else
700 if (tag == "METADATA_ALBUM") {
701 if (!value.isEmpty()) md.clip_album = value;
702 }
703 else
704 if (tag == "METADATA_COPYRIGHT") {
705 if (!value.isEmpty()) md.clip_copyright = value;
706 }
707 else
708 if (tag == "METADATA_TRACK") {
709 if (!value.isEmpty()) md.clip_track = value;
710 }
711 else
712 if (tag == "METADATA_GENRE") {
713 if (!value.isEmpty()) md.clip_genre = value;
714 }
715 else
716 if (tag == "INFO_MEDIA_TITLE") {
717 if (!value.isEmpty() && value != "mp4" && !value.startsWith("mp4&") /*&& md.clip_name.isEmpty()*/) {
718 md.clip_name = value;
719 }
720 }
721 else
722 if (tag == "MPV_VERSION") {
723 mpv_version = value;
724 //qDebug("MPVProcess::parseLine: mpv version: %s", mpv_version.toUtf8().constData());
725 }
726#if NOTIFY_VIDEO_CHANGES || NOTIFY_AUDIO_CHANGES || NOTIFY_SUB_CHANGES
727 else
728 if (tag == "INFO_TRACKS_COUNT") {
729 int tracks = value.toInt();
730 for (int n = 0; n < tracks; n++) {
731 writeToStdin(QString("print_text \"INFO_TRACK_%1: "
732 "${track-list/%1/type} "
733 "${track-list/%1/id} "
734 "'${track-list/%1/lang:}' "
735 "'${track-list/%1/title:}' "
736 "${track-list/%1/selected}\"").arg(n));
737 }
738 }
739#endif
740 }
741 }
742}
743
744void MPVProcess::requestChapterInfo() {
745 writeToStdin("print_text \"INFO_CHAPTERS=${=chapters}\"");
746}
747
748void MPVProcess::requestBitrateInfo() {
749 writeToStdin("print_text INFO_VIDEO_BITRATE=${=video-bitrate}");
750 writeToStdin("print_text INFO_AUDIO_BITRATE=${=audio-bitrate}");
751}
752
753#if NOTIFY_AUDIO_CHANGES
754void MPVProcess::updateAudioTrack(int ID, const QString & name, const QString & lang) {
755 qDebug("MPVProcess::updateAudioTrack: ID: %d", ID);
756
757 int idx = audios.find(ID);
758 if (idx == -1) {
759 audio_info_changed = true;
760 audios.addName(ID, name);
761 audios.addLang(ID, lang);
762 } else {
763 // Track already existed
764 if (audios.itemAt(idx).name() != name) {
765 audio_info_changed = true;
766 audios.addName(ID, name);
767 }
768 if (audios.itemAt(idx).lang() != lang) {
769 audio_info_changed = true;
770 audios.addLang(ID, lang);
771 }
772 }
773}
774#endif
775
776#if NOTIFY_SUB_CHANGES
777void MPVProcess::updateSubtitleTrack(int ID, const QString & name, const QString & lang) {
778 qDebug("MPVProcess::updateSubtitleTrack: ID: %d", ID);
779
780 int idx = subs.find(SubData::Sub, ID);
781 if (idx == -1) {
782 subtitle_info_changed = true;
783 subs.add(SubData::Sub, ID);
784 subs.changeName(SubData::Sub, ID, name);
785 subs.changeLang(SubData::Sub, ID, lang);
786 }
787 else {
788 // Track already existed
789 if (subs.itemAt(idx).name() != name) {
790 subtitle_info_changed = true;
791 subs.changeName(SubData::Sub, ID, name);
792 }
793 if (subs.itemAt(idx).lang() != lang) {
794 subtitle_info_changed = true;
795 subs.changeLang(SubData::Sub, ID, lang);
796 }
797 }
798}
799#endif
800
801// Called when the process is finished
802void MPVProcess::processFinished(int exitCode, QProcess::ExitStatus exitStatus) {
803 qDebug("MPVProcess::processFinished: exitCode: %d, status: %d", exitCode, (int) exitStatus);
804 // Send this signal before the endoffile one, otherwise
805 // the playlist will start to play next file before all
806 // objects are notified that the process has exited.
807 emit processExited();
808 if (received_end_of_file) emit receivedEndOfFile();
809}
810
811void MPVProcess::gotError(QProcess::ProcessError error) {
812 qDebug("MPVProcess::gotError: %d", (int) error);
813}
814
815#include "mpvoptions.cpp"
816#include "moc_mpvprocess.cpp"
Note: See TracBrowser for help on using the repository browser.