source: smplayer/trunk/src/mpvprocess.cpp

Last change on this file was 188, checked in by Silvan Scherrer, 8 years ago

SMPlayer: update trunk to version 17.1.0

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