void MediaObject::controlAvailable(QString const& name) { if (name == QMediaControl::name() && !d->valid) { d->control = new QMediaControl(d->content); connect(d->control, SIGNAL(playerStateChanged(QtopiaMedia::State)), SLOT(playerStateChanged(QtopiaMedia::State))); connect(d->control, SIGNAL(lengthChanged(quint32)), SLOT(lengthChanged(quint32))); d->valid = true; // Connect peers foreach (MediaNode* peer, d->peers) peer->setContent(d->content); switch (d->requiredState) { case QtopiaMedia::Playing: d->control->start(); break; default: ; } } bool hasVideo = d->content->controls().contains(QMediaVideoControl::name()); if (hasVideo != d->hasVideo) emit hasVideoChanged(d->hasVideo = hasVideo); }
void MediaObject::loadingFinished(MediaGraph *mg) { if (mg == currentGraph()) { #ifndef QT_NO_PHONON_MEDIACONTROLLER //Title interface m_currentTitle = 0; setTitles(currentGraph()->titles()); #endif //QT_NO_PHONON_MEDIACONTROLLER HRESULT hr = mg->renderResult(); if (catchComError(hr)) { return; } if (m_oldHasVideo != currentGraph()->hasVideo()) { emit hasVideoChanged(currentGraph()->hasVideo()); } #ifndef QT_NO_PHONON_VIDEO if (currentGraph()->hasVideo()) { updateVideoGeometry(); } #endif //QT_NO_PHONON_VIDEO emit metaDataChanged(currentGraph()->metadata()); emit totalTimeChanged(totalTime()); //let's put the next state switch(m_nextState) { case Phonon::PausedState: pause(); break; case Phonon::PlayingState: play(); break; case Phonon::ErrorState: setState(Phonon::ErrorState); break; case Phonon::StoppedState: default: stop(); break; } } }
void MediaObject::switchToNextSource() { m_prefinishMarkSent = false; m_aboutToFinishSent = false; m_nextSourceReadyToStart = false; m_oldHasVideo = currentGraph()->hasVideo(); qSwap(m_graphs[0], m_graphs[1]); //swap the graphs if (m_transitionTime >= 0) m_graphs[1]->stop(); //make sure we stop the previous graph if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid && catchComError(currentGraph()->renderResult())) { setState(Phonon::ErrorState); return; } //we need to play the next media play(); //we tell the video widgets to switch now to the new source #ifndef QT_NO_PHONON_VIDEO for (int i = 0; i < m_videoWidgets.count(); ++i) { m_videoWidgets.at(i)->setCurrentGraph(currentGraph()->index()); } #endif //QT_NO_PHONON_VIDEO emit currentSourceChanged(currentGraph()->mediaSource()); emit metaDataChanged(currentGraph()->metadata()); if (nextGraph()->hasVideo() != currentGraph()->hasVideo()) { emit hasVideoChanged(currentGraph()->hasVideo()); } emit tick(0); emit totalTimeChanged(totalTime()); #ifndef QT_NO_PHONON_MEDIACONTROLLER setTitles(currentGraph()->titles()); #endif //QT_NO_PHONON_MEDIACONTROLLER }
/* * !reimp */ void MediaObject::setSource(const MediaSource &source) { QMultiMap<QString, QString> ret; ret.insert(QLatin1String("ARTIST"), "Nokia Dude"); ret.insert(QLatin1String("ALBUM"), "Sound of silence"); ret.insert(QLatin1String("DATE"), "2009"); m_error = Phonon::NoError; setState(Phonon::LoadingState); m_source = source; currentPos = 0; if((source.fileName().contains(".avi")) || (source.fileName().contains(".mp4"))) { m_hasVideo = true; emit hasVideoChanged(m_hasVideo); } if(source.fileName().contains(".wav")) { QFile file(source.fileName()); if (file.open(QIODevice::ReadOnly)) { int len = file.read((char*)&header, sizeof(CombinedHeader)); if(len == sizeof(CombinedHeader)) { if(memcmp(&header.riff.descriptor.id, riffId, 4) != 0) { // Not a valid wav file, to satisfy unit test for mediaobject m_error = Phonon::FatalError; //m_state = Phonon::ErrorState; m_errorString = "Invalid wav file"; setState(Phonon::ErrorState); file.close(); return; } } file.close(); } } emit metaDataChanged(ret); emit currentSourceChanged(source); emit totalTimeChanged(m_totalTime); setState(Phonon::StoppedState); }
PlayEngine::PlayEngine() : d(new Data(this)) { Q_ASSERT(d->confDir.isValid()); _Debug("Create audio/video plugins"); d->audio = new AudioController(this); d->video = new VideoOutput(this); d->filter = new VideoFilter; d->chapterInfo = new ChapterInfoObject(this, this); d->updateMediaName(); _Debug("Make registrations and connections"); connect(d->video, &VideoOutput::formatChanged, this, &PlayEngine::updateVideoFormat); connect(d->video, &VideoOutput::droppedFramesChanged, this, &PlayEngine::droppedFramesChanged); d->handle = mpv_create(); auto verbose = qgetenv("CMPLAYER_MPV_VERBOSE").toLower().trimmed(); const QVector<QByteArray> lvs = {"no", "fatal", "error", "warn", "info", "status", "v", "debug", "trace"}; if (lvs.indexOf(verbose) < lvs.indexOf("info")) verbose = "info"; mpv_request_log_messages(d->handle, verbose.constData()); d->observe(); connect(this, &PlayEngine::beginChanged, this, &PlayEngine::endChanged); connect(this, &PlayEngine::durationChanged, this, &PlayEngine::endChanged); connect(this, &PlayEngine::videoStreamsChanged, this, [=] () { if (_Change(d->hasVideo, !d->streams[StreamVideo].tracks.isEmpty())) emit hasVideoChanged(); d->videoInfo.setTracks(d->streams[StreamVideo].tracks); }); connect(this, &PlayEngine::audioStreamsChanged, this, [=] () { d->audioInfo.setTracks(d->streams[StreamAudio].tracks); }); connect(this, &PlayEngine::subtitleStreamsChanged, this, [=] () { d->subInfo.setTracks(d->streams[StreamSubtitle].tracks); }); connect(this, &PlayEngine::currentVideoStreamChanged, this, [=] (int id) { d->videoInfo.setTrack(d->streams[StreamVideo].tracks.value(id)); }); connect(this, &PlayEngine::currentAudioStreamChanged, this, [=] (int id) { d->audioInfo.setTrack(d->streams[StreamAudio].tracks.value(id)); }); connect(this, &PlayEngine::currentSubtitleStreamChanged, this, [=] () { d->subInfo.setTracks(d->streams[StreamSubtitle].tracks); }); auto checkDeint = [=] () { auto act = Unavailable; if (d->filter->isInputInterlaced()) act = d->filter->isOutputInterlaced() ? Deactivated : Activated; d->videoInfo.setDeinterlacer(act); }; connect(d->filter, &VideoFilter::inputInterlacedChanged, this, checkDeint, Qt::QueuedConnection); connect(d->filter, &VideoFilter::outputInterlacedChanged, this, checkDeint, Qt::QueuedConnection); connect(d->audio, &AudioController::inputFormatChanged, this, [=] () { d->audioInfo.output()->setFormat(d->audio->inputFormat()); }, Qt::QueuedConnection); connect(d->audio, &AudioController::outputFormatChanged, this, [=] () { d->audioInfo.renderer()->setFormat(d->audio->outputFormat()); }, Qt::QueuedConnection); connect(d->audio, &AudioController::samplerateChanged, this, [=] (int sr) { d->audioInfo.renderer()->setSampleRate(sr, true); }, Qt::QueuedConnection); connect(d->audio, &AudioController::gainChanged, &d->audioInfo, &AudioInfoObject::setNormalizer); auto setOption = [this] (const char *name, const char *data) { const auto err = mpv_set_option_string(d->handle, name, data); d->fatal(err, "Couldn't set option %%=%%.", name, data); }; setOption("fs", "no"); setOption("input-cursor", "yes"); setOption("softvol", "yes"); setOption("softvol-max", "1000.0"); setOption("sub-auto", "no"); setOption("osd-level", "0"); setOption("quiet", "yes"); setOption("input-terminal", "no"); setOption("ad-lavc-downmix", "no"); setOption("title", "\"\""); setOption("vo", d->vo().constData()); setOption("fixed-vo", "yes"); auto overrides = qgetenv("CMPLAYER_MPV_OPTIONS").trimmed(); if (!overrides.isEmpty()) { const auto opts = QString::fromLocal8Bit(overrides); const auto args = opts.split(QRegEx(uR"([\s\t]+)"_q), QString::SkipEmptyParts); for (int i=0; i<args.size(); ++i) { if (!args[i].startsWith("--"_a)) { _Error("Cannot parse option %%.", args[i]); continue; } const auto arg = args[i].midRef(2); const int index = arg.indexOf('='_q); if (index < 0) { if (arg.startsWith("no-"_a)) setOption(arg.mid(3).toLatin1(), "no"); else setOption(arg.toLatin1(), "yes"); } else { const auto key = arg.left(index).toLatin1(); const auto value = arg.mid(index+1).toLatin1(); setOption(key, value); } } } d->fatal(mpv_initialize(d->handle), "Couldn't initialize mpv."); _Debug("Initialized"); d->initialized = true; }
void MPlayerProcess::parseLine(const QString & tmp) { QString line = tmp; //Skip empty lines if (line.isEmpty()) { return; } //Skip repeatitive lines if (line.contains("Too many buffered pts") || line.contains("pts value <= previous")) { return; } //Parse A: V: line if (rx_av.indexIn(line) > -1) { _mediaData.currentTime = (qint64) (rx_av.cap(1).toDouble() * SECONDS_CONVERTION); if (_currentState != Phonon::PlayingState) { qDebug() << __FUNCTION__ << "Starting time:" << _mediaData.currentTime; changeState(Phonon::PlayingState); //OK, now all the media datas should be in clean state emit mediaLoaded(); } emit tick(_mediaData.currentTime); //Check for frame number if (rx_frame.indexIn(line) > -1) { int frame = rx_frame.cap(1).toInt(); //qDebug() << __FUNCTION__ << "Frame number:" << frame; emit currentFrameNumberReceived(frame); } } //Parse other things else { qDebug() << "MPlayer:" << line; //Loading the file/stream/media //Becarefull! "Playing" does not mean the file is playing but only loading if (rx_playing.indexIn(line) > -1) { changeState(Phonon::LoadingState); } //File not found else if (rx_file_not_found.indexIn(line) > -1) { _errorString = "File not found"; _errorType = Phonon::NormalError; changeState(Phonon::ErrorState); } //Screenshot else if (rx_screenshot.indexIn(line) > -1) { const QString filename = rx_screenshot.cap(1); qDebug() << __FUNCTION__ << "Screenshot:" << filename; emit screenshotSaved(filename); } //End of file else if (rx_endoffile.indexIn(line) > -1) { qDebug() << __FUNCTION__ << "End of file detected"; //In case of playing VCDs or DVDs, maybe the first title //is not playable, so the GUI doesn't get the info about //available titles. So if we received the end of file //first let's pretend the file has started so the GUI can have //the data. if (_currentState != Phonon::PlayingState) { changeState(Phonon::PlayingState); } //Sends the endOfFileReached() signal once the process is finished, not now! _endOfFileReached = true; } //Window resolution else if (rx_winresolution.indexIn(line) > -1) { int width = rx_winresolution.cap(4).toInt(); int height = rx_winresolution.cap(5).toInt(); qDebug() << __FUNCTION__ << "Video driver:" << rx_winresolution.cap(1); //Now we know the real video size emit videoWidgetSizeChanged(width, height); //Ok, now we can be in PlayingState if we have a video stream //If we have only an audio stream, we are already in PlayingState changeState(Phonon::PlayingState); //emit mplayerFullyLoaded(); } //No video else if (rx_novideo.indexIn(line) > -1) { _mediaData.hasVideo = false; qDebug() << __FUNCTION__ << "Video:" << _mediaData.hasVideo; emit hasVideoChanged(_mediaData.hasVideo); //emit mplayerFullyLoaded(); } //Pause else if (rx_paused.indexIn(line) > -1) { changeState(Phonon::PausedState); } //Stream title and url else if (rx_stream_title.indexIn(line) > -1) { QString title = rx_stream_title.cap(1); QString url = rx_stream_title.cap(2); qDebug() << __FUNCTION__ << "Stream title:" << title; qDebug() << __FUNCTION__ << "Stream url:" << url; _mediaData.title = title; if (!url.isEmpty() && url.at(url.size() - 1) == '/') { url.remove(url.size() - 1, 1); } _mediaData.streamUrl = url; emit mediaDataChanged(_mediaData); } //Stream title only else if (rx_stream_title_only.indexIn(line) > -1) { QString title = rx_stream_title_only.cap(1); qDebug() << __FUNCTION__ << "Stream title:" << title; _mediaData.title = title; emit mediaDataChanged(_mediaData); } //The following things are not sent when the file has started to play //(or if sent, GUI will ignore anyway...) //So not process anymore, if video is playing to save some time if (_currentState == Phonon::PlayingState) { return; } /// else if ((_mplayerVersion == MPlayerProcess::MPLAYER_VERSION_NOTFOUND) && (line.startsWith("MPlayer "))) { _mplayerVersion = MPlayerVersion::parse(line); } //Stream name else if (rx_stream_name.indexIn(line) > -1) { QString name = rx_stream_name.cap(1); qDebug() << __FUNCTION__ << "Stream name:" << name; _mediaData.streamName = name; } //Stream genre else if (rx_stream_genre.indexIn(line) > -1) { QString genre = rx_stream_genre.cap(1); qDebug() << __FUNCTION__ << "Stream genre:" << genre; _mediaData.streamGenre = genre; } //Stream website else if (rx_stream_website.indexIn(line) > -1) { QString website = rx_stream_website.cap(1); qDebug() << __FUNCTION__ << "Stream website:" << website; if (!website.isEmpty() && website.at(website.size() - 1) == '/') { website.remove(website.size() - 1, 1); } _mediaData.streamWebsite = website; } //Subtitle //static QRegExp rx_subtitle("^ID_(SUBTITLE|FILE_SUB|VOBSUB)_ID=(\\d+)"); else if (rx_subtitle.indexIn(line) > -1) { //DVD line example: //subtitle ( sid ): 1 language: en //ID_SUBTITLE_ID=1 //ID_SID_1_LANG=en //subtitle ( sid ): 3 language: fr //ID_SUBTITLE_ID=3 //ID_SID_3_LANG=fr //subtitle ( sid ): 4 language: unknown //ID_SUBTITLE_ID=4 //Warning! ---> No ID_SID... //.str file example: //SUB: Detected subtitle file format: subviewer //SUB: Read 612 subtitles. //ID_FILE_SUB_ID=0 //ID_FILE_SUB_FILENAME=D:/The Ring CD1.srt //SUB: Added subtitle file (1): D:/The Ring CD1.srt //Matroska line example: //ID_SUBTITLE_ID=0 //ID_SID_0_NAME=Piste de présentation //[mkv] Track ID 4: subtitles (S_TEXT/UTF8) Piste de présentation, -sid 0, -slang mis //ID_SUBTITLE_ID=1 //ID_SID_1_LANG=fre //[mkv] Track ID 5: subtitles (S_VOBSUB), -sid 1, -slang fre //ID_SUBTITLE_ID=2 //ID_SID_2_LANG=eng //int id = rx_subtitle.cap(2).toInt(); const QString type = rx_subtitle.cap(1); if (type == "FILE_SUB") { } else if (type == "VOBSUB") { } else if (type == "SUBTITLE") { } } //Subtitle //static QRegExp rx_sid("^ID_(SID|VSID)_(\\d+)_(LANG|NAME)=(.*)"); else if (rx_sid.indexIn(line) > -1) { int id = rx_sid.cap(2).toInt(); const QString lang = rx_sid.cap(4); const QString attr = rx_sid.cap(3); const QString type = rx_sid.cap(1); qDebug() << __FUNCTION__ << "Subtitle id:" << id << "lang:" << lang << "type:" << type << "attr:" << attr; if (type == "VSID") { } else if (type == "SID") { } if (attr == "NAME") { } else if (attr == "LANG") { } emit subtitleAdded(id, lang, type); } //Subtitle //static QRegExp rx_subtitle_file("^SUB: Added subtitle file \\((\\d+)\\): (.*)"); else if (rx_subtitle_file.indexIn(line) > -1) { //MPlayer make the id start at number 1, //we want it to start at number 0 int id = rx_subtitle_file.cap(1).toInt() - 1; const QString fileName = rx_subtitle_file.cap(2); qDebug() << __FUNCTION__ << "Subtitle id:" << id << "file:" << fileName; emit subtitleAdded(id, fileName, "file"); if (id == 0) { qDebug() << __FUNCTION__ << "Current subtitle changed:" << id; emit subtitleChanged(0); } } //AO else if (rx_ao.indexIn(line) > -1) { //emit receivedAO(rx_ao.cap(1)); } //DVD and Matroska audio tracks else if (rx_audio_mat.indexIn(line) > -1) { //DVD examples: //ID_AUDIO_ID=129 //ID_AID_129_LANG=fr //ID_AUDIO_ID=128 //ID_AID_128_LANG=en //Matroska examples: //[mkv] Track ID 1: video (V_REAL/RV40), -vid 0 //ID_AUDIO_ID=0 //ID_AID_0_LANG=fre //[mkv] Track ID 3: audio (A_AAC/MPEG4/LC/SBR), -aid 1, -alang eng //ID_SUBTITLE_ID=0 //ID_SID_0_NAME=Piste de présentation //[mkv] Track ID 4: subtitles (S_TEXT/UTF8) Piste de présentation, -sid 0, -slang mis //ID_SUBTITLE_ID=1 //ID_SID_1_LANG=fre //[mkv] Track ID 5: subtitles (S_VOBSUB), -sid 1, -slang fre //ID_SUBTITLE_ID=2 //ID_SID_2_LANG=eng //[mkv] Track ID 6: subtitles (S_VOBSUB), -sid 2, -slang eng //[mkv] Will play video track 1. //Matroska file format detected. //VIDEO: [RV40] 704x296 24bpp 25.000 fps 0.0 kbps ( 0.0 kbyte/s) int id = rx_audio_mat.cap(1).toInt(); QString lang = rx_audio_mat.cap(3); QString attr = rx_audio_mat.cap(2); qDebug() << __FUNCTION__ << "Audio id:" << id << "lang:" << lang << "attr:" << attr; if (attr == "NAME") { //lang=english, spanish... //_mediaData.audioTrackList.addName(id, lang); } else if (attr == "LANG") { //lang=en, fr... //_mediaData.audioTrackList.addLang(id, lang); } emit audioChannelAdded(id, lang); } //static QRegExp rx_mkvchapters("\\[mkv\\] Chapter (\\d+) from (.*) to (.*), (.*)"); //Matroska chapters else if (rx_mkvchapters.indexIn(line) != -1) { //Examples: //[mkv] Chapter 0 from 00:10:09.800 to 00:00:00.000, La Cellule //[mkv] Chapter 1 from 00:15:02.080 to 00:00:00.000, Plus l'on Approche de César //[mkv] Chapter 2 from 00:19:16.400 to 00:00:00.000, La Compagnie Charlie //[mkv] Chapter 3 from 00:24:41.520 to 00:00:00.000, Guadalcanal int id = rx_mkvchapters.cap(1).toInt(); QString from = rx_mkvchapters.cap(2); QString to = rx_mkvchapters.cap(3); QString title = rx_mkvchapters.cap(4); qDebug() << __FUNCTION__ << "mkv chapter:" << id << "title:" << title << "from:" << from << "to:" << to; emit mkvChapterAdded(id, title, from, to); } //VCD titles /*else if (rx_vcd.indexIn(line) > -1) { int ID = rx_vcd.cap(1).toInt(); QString length = rx_vcd.cap(2); //_mediaData.titles.addID(ID); _mediaData.titles.addName(ID, length); } else //Audio CD titles if (rx_cdda.indexIn(line) > -1) { int ID = rx_cdda.cap(1).toInt(); QString length = rx_cdda.cap(2); double duration = 0; QRegExp r("(\\d+):(\\d+):(\\d+)"); if (r.indexIn(length) > -1) { duration = r.cap(1).toInt() * 60; duration += r.cap(2).toInt(); } _mediaData.titles.addID(ID); //QString name = QString::number(ID) + " (" + length + ")"; //_mediaData.titles.addName(ID, name); _mediaData.titles.addDuration(ID, duration); } else*/ //DVD titles else if (rx_titles.indexIn(line) > -1) { //Available DVD titles //int titles = rx_title.cap(1).toInt(); } else if (rx_title.indexIn(line) > -1) { //DVD example: //ID_DVD_TITLES=8 //ID_DVD_TITLE_1_CHAPTERS=2 //ID_DVD_TITLE_1_ANGLES=1 //ID_DVD_TITLE_2_CHAPTERS=12 //ID_DVD_TITLE_2_ANGLES=1 //ID_DVD_TITLE_1_LENGTH=18.560 //ID_DVD_TITLE_2_LENGTH=5055.000 //ID_DVD_DISC_ID=6B5CDFED561E882B949047C87A88BCB4 //ID_DVD_CURRENT_TITLE=1 int titleId = rx_title.cap(1).toInt(); const QString attr = rx_title.cap(2); if (attr == "CHAPTERS") { int chapters = rx_title.cap(3).toInt(); qDebug() << __FUNCTION__ << "DVD titleId:" << titleId << "chapters:" << chapters; emit chapterAdded(titleId, chapters); } else if (attr == "ANGLES") { int angles = rx_title.cap(3).toInt(); qDebug() << __FUNCTION__ << "DVD titleId:" << titleId << "angles:" << angles; emit angleAdded(titleId, angles); } else if (attr == "LENGTH") { double length = rx_title.cap(3).toDouble(); qDebug() << __FUNCTION__ << "DVD titleId:" << titleId << "length:" << length << "attr:" << attr; emit titleAdded(titleId, (int) (length * SECONDS_CONVERTION)); } } //Creating index else if (rx_create_index.indexIn(line) > -1) { emit receivedCreatingIndex(line); } //Catch resolving message else if (rx_resolving.indexIn(line) > -1) { QString msg = rx_resolving.cap(1); qDebug() << __FUNCTION__ << "Resolving:" << msg; emit resolvingMessageReceived(msg); } //Catch resolving failed else if (rx_resolving_failed.indexIn(line) > -1) { _errorString = line; _errorType = Phonon::NormalError; changeState(Phonon::ErrorState); } //Catch connecting message else if (rx_connecting.indexIn(line) > -1) { QString msg = rx_connecting.cap(1); qDebug() << __FUNCTION__ << "Connecting:" << msg; emit connectingMessageReceived(msg); changeState(Phonon::BufferingState); } else if (rx_read_failed.indexIn(line) > -1) { _errorString = "Cannot read the network stream"; _errorType = Phonon::NormalError; changeState(Phonon::ErrorState); } //Catch cache messages else if (rx_cache_fill.indexIn(line) > -1) { QString tmp = rx_cache_fill.cap(1); tmp = tmp.trimmed(); float percentFilled = tmp.toFloat(); qDebug() << __FUNCTION__ << "Cache %:" << percentFilled << tmp; emit bufferStatus(static_cast<int>(percentFilled)); } //Meta data infos //Title else if (rx_clip_title.indexIn(line) > -1) { QString title = rx_clip_title.cap(2); qDebug() << __FUNCTION__ << "Clip title:" << title; _mediaData.title = title; } //Artist else if (rx_clip_artist.indexIn(line) > -1) { QString artist = rx_clip_artist.cap(1); qDebug() << __FUNCTION__ << "Clip artist:" << artist; _mediaData.artist = artist; } //Author else if (rx_clip_author.indexIn(line) > -1) { QString author = rx_clip_author.cap(1); qDebug() << __FUNCTION__ << "Clip author:" << author; _mediaData.author = author; } //Album else if (rx_clip_album.indexIn(line) > -1) { QString album = rx_clip_album.cap(1); qDebug() << __FUNCTION__ << "Clip album:" << album; _mediaData.album = album; } //Genre else if (rx_clip_genre.indexIn(line) > -1) { QString genre = rx_clip_genre.cap(1); qDebug() << __FUNCTION__ << "Clip genre:" << genre; _mediaData.genre = genre; } //Date else if (rx_clip_date.indexIn(line) > -1) { QString date = rx_clip_date.cap(2); qDebug() << __FUNCTION__ << "Clip date:" << date; _mediaData.date = date; } //Track else if (rx_clip_track.indexIn(line) > -1) { QString track = rx_clip_track.cap(1); qDebug() << __FUNCTION__ << "Clip track:" << track; _mediaData.track = track; } //Copyright else if (rx_clip_copyright.indexIn(line) > -1) { QString copyright = rx_clip_copyright.cap(1); qDebug() << __FUNCTION__ << "Clip copyright:" << copyright; _mediaData.copyright = copyright; } //Comment else if (rx_clip_comment.indexIn(line) > -1) { QString comment = rx_clip_comment.cap(1); qDebug() << __FUNCTION__ << "Clip comment:" << comment; _mediaData.comment = comment; } //Software else if (rx_clip_software.indexIn(line) > -1) { QString software = rx_clip_software.cap(1); qDebug() << __FUNCTION__ << "Clip software:" << software; _mediaData.software = software; } //Catch "Starting playback..." message else if (rx_play.indexIn(line) > -1) { //OK, now all the media datas should be in clean state //Second time we emit mediaLoaded(), this one is usefull for DVD with angles/chapters/subtitles... //This must be changed, see MediaObject::mediaLoaded() emit mediaLoaded(); emit mediaDataChanged(_mediaData); if (_mediaData.hasVideo) { //If we have a video to display, wait for getting the video size //before to be in PlayingState //This is a bugfix for mediaplayer example from Trolltech } else { //For audio streams, it's ok we are in PlayingState changeState(Phonon::PlayingState); } } //Generic things if (rx_generic.indexIn(line) > -1) { const QString tag = rx_generic.cap(1); const QString value = rx_generic.cap(2); if (tag == "ID_VIDEO_ID") { //First string to tell us that the media contains a video track _mediaData.hasVideo = true; qDebug() << __FUNCTION__ << "Video:" << _mediaData.hasVideo; emit hasVideoChanged(_mediaData.hasVideo); } else if (tag == "ID_AUDIO_ID") { //First string to tell us that the media contains an audio track /*int audioId = value.toInt(); qDebug() << __FUNCTION__ << "ID_AUDIO_ID:" << audioId; md.audios.addID(audioId);*/ } else if (tag == "ID_LENGTH") { _mediaData.totalTime = (qint64) (value.toDouble() * SECONDS_CONVERTION); qDebug() << __FUNCTION__ << "Media total time:" << _mediaData.totalTime; emit totalTimeChanged(_mediaData.totalTime); } else if (tag == "ID_SEEKABLE") { _mediaData.isSeekable = value.toInt(); qDebug() << __FUNCTION__ << "Media seekable:" << _mediaData.isSeekable; emit seekableChanged(_mediaData.isSeekable); } else if (tag == "ID_VIDEO_WIDTH") { _mediaData.videoWidth = value.toInt(); qDebug() << __FUNCTION__ << "Video width:" << _mediaData.videoWidth; } else if (tag == "ID_VIDEO_HEIGHT") { _mediaData.videoHeight = value.toInt(); qDebug() << __FUNCTION__ << "Video height:" << _mediaData.videoHeight; } else if (tag == "ID_VIDEO_ASPECT") { _mediaData.videoAspectRatio = value.toDouble(); if (_mediaData.videoAspectRatio == 0.0) { //I hope width & height are already set _mediaData.videoAspectRatio = (double) _mediaData.videoWidth / _mediaData.videoHeight; } qDebug() << __FUNCTION__ << "Video aspect:" << _mediaData.videoAspectRatio; } else if (tag == "ID_DVD_DISC_ID") { //_mediaData.dvd_id = value; qDebug() << __FUNCTION__ << "DVD disc Id:" << value; } else if (tag == "ID_DEMUXER") { _mediaData.demuxer = value; } else if (tag == "ID_VIDEO_FORMAT") { _mediaData.videoFormat = value; } else if (tag == "ID_AUDIO_FORMAT") { _mediaData.audioFormat = value; } else if (tag == "ID_VIDEO_BITRATE") { _mediaData.videoBitrate = value.toInt(); } else if (tag == "ID_VIDEO_FPS") { _mediaData.videoFPS = value.toDouble(); qDebug() << __FUNCTION__ << "Video FPS:" << _mediaData.videoFPS; } else if (tag == "ID_AUDIO_BITRATE") { _mediaData.audioBitrate = value.toInt(); } else if (tag == "ID_AUDIO_RATE") { _mediaData.audioRate = value.toInt(); } else if (tag == "ID_AUDIO_NCH") { _mediaData.audioNbChannels = value.toInt(); } else if (tag == "ID_VIDEO_CODEC") { _mediaData.videoCodec = value; } else if (tag == "ID_AUDIO_CODEC") { _mediaData.audioCodec = value; } else if (tag == "ID_DVD_CURRENT_TITLE") { int id = value.toInt(); if (_currentTitleId != id) { _currentTitleId = id; emit titleChanged(_currentTitleId); } } } } }