File indexing completed on 2024-03-24 04:56:59
0001 /* 0002 SPDX-FileCopyrightText: 2002-2003 Koos Vriezen <koos.vriezen@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "config-kmplayer.h" 0008 0009 #include <cmath> 0010 0011 #include <QApplication> 0012 #include <QByteArray> 0013 #include <QCursor> 0014 #include <QTimer> 0015 #include <QPair> 0016 #include <QPushButton> 0017 #include <QStandardPaths> 0018 #include <QSlider> 0019 #include <QFile> 0020 #include <QRegExp> 0021 #include <QProcess> 0022 #include <QDBusConnection> 0023 #include <QDBusMessage> 0024 #include <QMimeDatabase> 0025 #include <QMimeType> 0026 0027 #include <KMessageBox> 0028 #include <KAboutData> 0029 #include <KBookmarkMenu> 0030 #include <KBookmarkManager> 0031 #include <KBookmark> 0032 #include <KConfig> 0033 #include <KConfigGroup> 0034 #include <KIconLoader> 0035 #include <KLocalizedString> 0036 #include <KProtocolInfo> 0037 #include <KIO/Global> 0038 #include <KIO/Job> 0039 #include <KUrlAuthorized> 0040 0041 #include "kmplayercommon_log.h" 0042 #include "kmplayerpartbase.h" 0043 #include "kmplayerview.h" 0044 #include "playmodel.h" 0045 #include "playlistview.h" 0046 #include "kmplayerprocess.h" 0047 #include "viewarea.h" 0048 #include "kmplayercontrolpanel.h" 0049 #include "kmplayerconfig.h" 0050 #include "kmplayer_smil.h" 0051 #include "mediaobject.h" 0052 #include "partadaptor.h" 0053 0054 namespace KMPlayer { 0055 0056 class BookmarkOwner : public KBookmarkOwner { 0057 public: 0058 BookmarkOwner (PartBase *); 0059 ~BookmarkOwner () override {} 0060 void openBookmark(const KBookmark &bm, Qt::MouseButtons mb, Qt::KeyboardModifiers km) override; 0061 QString currentTitle() const override; 0062 QString currentURL() const; 0063 private: 0064 PartBase * m_player; 0065 }; 0066 0067 } // namespace 0068 0069 using namespace KMPlayer; 0070 0071 BookmarkOwner::BookmarkOwner (PartBase * player) 0072 : m_player (player) {} 0073 0074 void BookmarkOwner::openBookmark(const KBookmark &bm, Qt::MouseButtons, Qt::KeyboardModifiers) { 0075 if (!bm.isNull ()) 0076 m_player->openUrl (bm.url ()); 0077 } 0078 0079 QString BookmarkOwner::currentTitle () const { 0080 return m_player->source ()->prettyName (); 0081 } 0082 0083 QString BookmarkOwner::currentURL () const { 0084 return m_player->source ()->url ().url (); 0085 } 0086 0087 //----------------------------------------------------------------------------- 0088 0089 PartBase::PartBase (QWidget * wparent, QObject * parent, KSharedConfigPtr config) 0090 : KMediaPlayer::Player (wparent, "kde_kmplayer_part", parent), 0091 m_config (config), 0092 m_view (new View (wparent)), 0093 m_settings (new Settings (this, config)), 0094 m_media_manager (new MediaManager (this)), 0095 m_play_model (new PlayModel (this, KIconLoader::global ())), 0096 m_source (nullptr), 0097 m_bookmark_menu (nullptr), 0098 m_update_tree_timer (0), 0099 m_rec_timer (0), 0100 m_noresize (false), 0101 m_auto_controls (true), 0102 m_bPosSliderPressed (false), 0103 m_in_update_tree (false), 0104 m_update_tree_full (false) 0105 { 0106 m_sources ["urlsource"] = new URLSource (this); 0107 0108 QString bmfile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmplayer/bookmarks.xml"); 0109 QString localbmfile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kmplayer/bookmarks.xml"; 0110 if (localbmfile != bmfile) { 0111 bool bmfileCopied = QFile(bmfile).copy(localbmfile); 0112 qCDebug(LOG_KMPLAYER_COMMON) << "bookmarks.xml copied successfully?" << bmfileCopied; 0113 } 0114 m_bookmark_manager = KBookmarkManager::managerForFile (localbmfile, "kmplayer"); 0115 m_bookmark_owner = new BookmarkOwner (this); 0116 } 0117 0118 void PartBase::showConfigDialog () { 0119 m_settings->show ("URLPage"); 0120 } 0121 0122 void PartBase::showPlayListWindow () { 0123 // note, this is also the slot of application's view_playlist action, but 0124 // anyhow, actions don't work for the fullscreen out-of-the-box, so ... 0125 if (m_view->viewArea ()->isFullScreen ()) 0126 fullScreen (); 0127 else if (m_view->viewArea ()->isMinimalMode ()) 0128 ; //done by app: m_view->viewArea ()->minimalMode (); 0129 else 0130 m_view->toggleShowPlaylist (); 0131 } 0132 0133 void PartBase::addBookMark (const QString & t, const QString & url) { 0134 KBookmarkGroup b = m_bookmark_manager->root (); 0135 b.addBookmark (t, QUrl (url), KIO::iconNameForUrl(QUrl(url))); 0136 m_bookmark_manager->emitChanged (b); 0137 } 0138 0139 void PartBase::init (KActionCollection * action_collection, const QString &objname, bool transparent) { 0140 KParts::Part::setWidget (m_view); 0141 m_view->init (action_collection, transparent); 0142 connect(m_settings, &Settings::configChanged, this, &PartBase::settingsChanged); 0143 m_settings->readConfig (); 0144 m_settings->applyColorSetting (false); 0145 connect (m_view, &View::urlDropped, 0146 this, QOverload<const QList<QUrl>&>::of(&PartBase::openUrl)); 0147 connectPlaylist (m_view->playList ()); 0148 connectInfoPanel (m_view->infoPanel ()); 0149 0150 (void) new PartAdaptor (this); 0151 QDBusConnection::sessionBus().registerObject (objname, this); 0152 } 0153 0154 void PartBase::connectPanel (ControlPanel * panel) { 0155 /*panel->contrastSlider ()->setValue (m_settings->contrast); 0156 panel->brightnessSlider ()->setValue (m_settings->brightness); 0157 panel->hueSlider ()->setValue (m_settings->hue); 0158 panel->saturationSlider ()->setValue (m_settings->saturation); 0159 panel->volumeBar ()->setValue (m_settings->volume);*/ 0160 connect (panel->button (ControlPanel::button_playlist), &QPushButton::clicked, this, &PartBase::showPlayListWindow); 0161 connect (panel->button (ControlPanel::button_back), &QPushButton::clicked, this, &PartBase::back); 0162 connect (panel->button (ControlPanel::button_play), &QPushButton::clicked, this, &PartBase::play); 0163 connect (panel->button (ControlPanel::button_forward), &QPushButton::clicked, this, &PartBase::forward); 0164 connect (panel->button (ControlPanel::button_pause), &QPushButton::clicked, this, &PartBase::pause); 0165 connect (panel->button (ControlPanel::button_stop), &QPushButton::clicked, this, &PartBase::stop); 0166 connect (panel->button (ControlPanel::button_record), &QPushButton::clicked, this, QOverload<>::of(&PartBase::record)); 0167 connect (panel->volumeBar (), &VolumeBar::volumeChanged, this, &PartBase::volumeChanged); 0168 connect (panel->positionSlider (), &QSlider::valueChanged, this, &PartBase::positionValueChanged); 0169 connect (panel->positionSlider (), &QSlider::sliderPressed, this, &PartBase::posSliderPressed); 0170 connect (panel->positionSlider (), &QSlider::sliderReleased, this, &PartBase::posSliderReleased); 0171 connect (this, &PartBase::positioned, panel, &ControlPanel::setPlayingProgress); 0172 connect (this, &PartBase::loading, panel, &ControlPanel::setLoadingProgress); 0173 /*connect (panel->contrastSlider (), SIGNAL (valueChanged(int)), this, SLOT (contrastValueChanged(int))); 0174 connect (panel->brightnessSlider (), SIGNAL (valueChanged(int)), this, SLOT (brightnessValueChanged(int))); 0175 connect (panel->hueSlider (), SIGNAL (valueChanged(int)), this, SLOT (hueValueChanged(int))); 0176 connect (panel->saturationSlider (), SIGNAL (valueChanged(int)), this, SLOT (saturationValueChanged(int)));*/ 0177 connect (this, &PartBase::languagesUpdated, 0178 panel, &ControlPanel::setLanguages); 0179 connect (panel->audioMenu, &QMenu::triggered, this, &PartBase::audioSelected); 0180 connect (panel->subtitleMenu, &QMenu::triggered, this, &PartBase::subtitleSelected); 0181 connect (panel->playerMenu, &QMenu::triggered, this, &PartBase::slotPlayerMenu); 0182 connect (this, &PartBase::panelActionToggled, panel, &ControlPanel::actionToggled); 0183 connect (panel->fullscreenAction, &QAction::triggered, 0184 this, &PartBase::fullScreen); 0185 connect (panel->configureAction, &QAction::triggered, 0186 this, &PartBase::showConfigDialog); 0187 connect (panel->videoConsoleAction, &QAction::triggered, 0188 m_view, &View::toggleVideoConsoleWindow); 0189 connect (panel->playlistAction, &QAction::triggered, 0190 m_view, &View::toggleShowPlaylist); 0191 connect (this, &PartBase::statusUpdated, 0192 panel->view (), &View::setStatusMessage); 0193 //connect (panel (), &QPushButton::clicked, m_settings, SLOT (show ())); 0194 } 0195 0196 void PartBase::createBookmarkMenu(QMenu *owner, KActionCollection *ac) { 0197 m_bookmark_menu = new KBookmarkMenu (m_bookmark_manager, m_bookmark_owner, owner, ac); 0198 } 0199 0200 void PartBase::connectPlaylist (PlayListView * playlist) { 0201 playlist->setModel (m_play_model); 0202 connect (m_play_model, &PlayModel::updating, 0203 playlist, &PlayListView::modelUpdating); 0204 connect (m_play_model, &PlayModel::updated, 0205 playlist, &PlayListView::modelUpdated); 0206 connect (playlist->selectionModel(), &QItemSelectionModel::currentChanged, 0207 playlist, &PlayListView::slotCurrentItemChanged); 0208 connect (playlist, QOverload<const QString &, const QString &>::of(&PlayListView::addBookMark), 0209 this, &PartBase::addBookMark); 0210 connect (playlist, &QTreeView::activated, 0211 this, &PartBase::playListItemActivated); 0212 connect (playlist, &QTreeView::clicked, 0213 this, &PartBase::playListItemClicked); 0214 connect (this, &PartBase::treeChanged, 0215 m_play_model, QOverload<int, NodePtr, NodePtr, bool, bool>::of(&PlayModel::updateTree)); 0216 } 0217 0218 void PartBase::connectInfoPanel (InfoWindow * infopanel) { 0219 connect (this, &PartBase::infoUpdated, 0220 infopanel->view (), &View::setInfoMessage); 0221 } 0222 0223 PartBase::~PartBase () { 0224 qCDebug(LOG_KMPLAYER_COMMON) << "PartBase::~PartBase"; 0225 m_view = (View*) nullptr; 0226 stopRecording (); 0227 stop (); 0228 if (m_source) 0229 m_source->deactivate (); 0230 delete m_media_manager; 0231 if (m_record_doc) 0232 m_record_doc->document ()->dispose (); 0233 delete m_settings; 0234 delete m_bookmark_menu; 0235 delete m_sources ["urlsource"]; 0236 //delete m_bookmark_manager; 0237 delete m_bookmark_owner; 0238 } 0239 0240 void PartBase::showControls (bool show) { 0241 viewWidget ()->setControlPanelMode ( 0242 show ? View::CP_Show : View::CP_Hide); 0243 } 0244 0245 QString PartBase::getStatus () { 0246 QString rval = "Waiting"; 0247 if (source() && source()->document()) { 0248 if (source()->document()->unfinished ()) 0249 rval = "Playable"; 0250 else if (source()->document()->state >= Node::state_deactivated) 0251 rval = "Complete"; 0252 } 0253 return rval; 0254 } 0255 0256 QString PartBase::doEvaluate (const QString &) { 0257 return "undefined"; 0258 } 0259 0260 void PartBase::settingsChanged () { 0261 if (!m_view) 0262 return; 0263 if (m_settings->showcnfbutton) 0264 m_view->controlPanel()->button (ControlPanel::button_config)->show(); 0265 else 0266 m_view->controlPanel()->button (ControlPanel::button_config)->hide(); 0267 m_view->controlPanel()->enableRecordButtons (m_settings->showrecordbutton); 0268 if (m_settings->showplaylistbutton) 0269 m_view->controlPanel()->button (ControlPanel::button_playlist)->show(); 0270 else 0271 m_view->controlPanel()->button (ControlPanel::button_playlist)->hide(); 0272 if (!m_settings->showbroadcastbutton) 0273 m_view->controlPanel ()->broadcastButton ()->hide (); 0274 keepMovieAspect (m_settings->sizeratio); 0275 m_settings->applyColorSetting (true); 0276 } 0277 0278 KMediaPlayer::View* PartBase::view () { 0279 return m_view; 0280 } 0281 0282 extern const char * strGeneralGroup; 0283 0284 QString PartBase::processName (Mrl *mrl) { 0285 if (id_node_grab_document == mrl->id) 0286 return QString ("mplayer"); //FIXME 0287 // determine backend, start with temp_backends 0288 QString p = temp_backends [m_source->name()]; 0289 bool remember_backend = p.isEmpty (); 0290 MediaManager::ProcessInfoMap &pinfos = m_media_manager->processInfos (); 0291 if (p.isEmpty ()) { 0292 // next try to find mimetype match from kmplayerrc 0293 if (!mrl->mimetype.isEmpty ()) { 0294 KConfigGroup mime_cfg (m_config, mrl->mimetype); 0295 p = mime_cfg.readEntry ("player", QString ()); 0296 remember_backend = !(!p.isEmpty () && 0297 pinfos.contains (p) && 0298 pinfos [p]->supports (m_source->name ())); 0299 } 0300 } 0301 if (p.isEmpty ()) 0302 // try source match from kmplayerrc 0303 p = m_settings->backends [m_source->name()]; 0304 if (p.isEmpty ()) { 0305 // try source match from kmplayerrc by re-reading 0306 p = KConfigGroup(m_config, strGeneralGroup).readEntry(m_source->name(),QString()); 0307 } 0308 if (p.isEmpty () || 0309 !pinfos.contains (p) || 0310 !pinfos [p]->supports (m_source->name ())) { 0311 // finally find first supported player 0312 p.truncate (0); 0313 const MediaManager::ProcessInfoMap::const_iterator e = pinfos.constEnd(); 0314 for (MediaManager::ProcessInfoMap::const_iterator i = pinfos.constBegin(); i != e; ++i) 0315 if (i.value ()->supports (m_source->name ())) { 0316 p = QString (i.value ()->name); 0317 break; 0318 } 0319 } 0320 if (!p.isEmpty ()) { 0321 updatePlayerMenu (m_view->controlPanel (), p); 0322 if (remember_backend) 0323 m_settings->backends [m_source->name()] = p; 0324 else 0325 temp_backends [m_source->name()] = QString (); 0326 } 0327 return p; 0328 } 0329 0330 void PartBase::processCreated (Process*) {} 0331 0332 void PartBase::slotPlayerMenu (QAction* act) { 0333 Mrl *mrl = m_source->current (); 0334 bool playing = mrl && mrl->active (); 0335 const char * srcname = m_source->name (); 0336 QMenu *player_menu = m_view->controlPanel ()->playerMenu; 0337 MediaManager::ProcessInfoMap &pinfos = m_media_manager->processInfos (); 0338 const MediaManager::ProcessInfoMap::const_iterator e = pinfos.constEnd(); 0339 int id = 0; 0340 for (MediaManager::ProcessInfoMap::const_iterator i = pinfos.constBegin(); 0341 id < player_menu->actions().count() && i != e; 0342 ++i) { 0343 ProcessInfo *pinfo = i.value (); 0344 if (!pinfo->supports (srcname)) 0345 continue; 0346 QAction* menu = player_menu->actions().at (id); 0347 menu->setChecked (menu == act); 0348 if (menu == act) { 0349 if (strcmp (pinfo->name, "npp")) 0350 m_settings->backends [srcname] = pinfo->name; 0351 temp_backends [srcname] = pinfo->name; 0352 } 0353 id++; 0354 } 0355 if (playing) 0356 m_source->play (mrl); 0357 } 0358 0359 void PartBase::updatePlayerMenu (ControlPanel *panel, const QString &backend) { 0360 if (!m_view) 0361 return; 0362 QMenu *menu = panel->playerMenu; 0363 menu->clear (); 0364 MediaManager::ProcessInfoMap &pinfos = m_media_manager->processInfos (); 0365 const MediaManager::ProcessInfoMap::const_iterator e = pinfos.constEnd(); 0366 for (MediaManager::ProcessInfoMap::const_iterator i = pinfos.constBegin(); i != e; ++i) { 0367 ProcessInfo *p = i.value (); 0368 if (p->supports (m_source ? m_source->name () : "urlsource")) { 0369 QAction* act = menu->addAction (p->label); 0370 act->setCheckable(true); 0371 if (backend == p->name) 0372 act->setChecked (true); 0373 } 0374 } 0375 } 0376 0377 void PartBase::connectSource (Source * old_source, Source * source) { 0378 if (old_source) { 0379 disconnect (old_source, &Source::endOfPlayItems, 0380 this, &PartBase::stop); 0381 disconnect (old_source, &Source::dimensionsChanged, 0382 this, &PartBase::sourceHasChangedAspects); 0383 disconnect (old_source, &Source::startPlaying, 0384 this, &PartBase::slotPlayingStarted); 0385 disconnect (old_source, &Source::stopPlaying, 0386 this, &PartBase::slotPlayingStopped); 0387 } 0388 if (source) { 0389 connect (source, &Source::endOfPlayItems, 0390 this, &PartBase::stop); 0391 connect (source, &Source::dimensionsChanged, 0392 this, &PartBase::sourceHasChangedAspects); 0393 connect (source, &Source::startPlaying, 0394 this, &PartBase::slotPlayingStarted); 0395 connect (source, &Source::stopPlaying, 0396 this, &PartBase::slotPlayingStopped); 0397 } 0398 } 0399 0400 void PartBase::setSource (Source * _source) { 0401 Source * old_source = m_source; 0402 if (m_source) { 0403 m_source->deactivate (); 0404 stop (); 0405 if (m_view) { 0406 m_view->reset (); 0407 Q_EMIT infoUpdated (QString ()); 0408 } 0409 disconnect (this, &PartBase::audioIsSelected, 0410 m_source, &Source::setAudioLang); 0411 disconnect (this, &PartBase::subtitleIsSelected, 0412 m_source, &Source::setSubtitle); 0413 } 0414 if (m_view) { 0415 if (m_auto_controls) 0416 m_view->controlPanel ()->setAutoControls (m_auto_controls); 0417 m_view->controlPanel ()->enableRecordButtons (m_settings->showrecordbutton); 0418 if (!m_settings->showcnfbutton) 0419 m_view->controlPanel()->button(ControlPanel::button_config)->hide(); 0420 if (!m_settings->showplaylistbutton) 0421 m_view->controlPanel()->button(ControlPanel::button_playlist)->hide(); 0422 } 0423 m_source = _source; 0424 connectSource (old_source, m_source); 0425 connect (this, &PartBase::audioIsSelected, 0426 m_source, &Source::setAudioLang); 0427 connect (this, &PartBase::subtitleIsSelected, 0428 m_source, &Source::setSubtitle); 0429 m_source->init (); 0430 m_source->setIdentified (false); 0431 if (m_view) 0432 updatePlayerMenu (m_view->controlPanel ()); 0433 if (m_source && !m_source->avoidRedirects ()) 0434 QTimer::singleShot (0, m_source, &Source::slotActivate); 0435 updateTree (true, true); 0436 Q_EMIT sourceChanged (old_source, m_source); 0437 } 0438 0439 void PartBase::changeURL (const QString & url) { 0440 Q_EMIT urlChanged (url); 0441 } 0442 0443 bool PartBase::isSeekable (void) const { 0444 return m_source ? m_source->isSeekable () : false; 0445 } 0446 0447 bool PartBase::hasLength () const { 0448 return m_source ? m_source->hasLength () : false; 0449 } 0450 0451 qlonglong PartBase::length () const { 0452 return m_source ? m_source->length () : 0; 0453 } 0454 0455 bool PartBase::openUrl (const QUrl &url) { 0456 qCDebug(LOG_KMPLAYER_COMMON) << "PartBase::openUrl " << url.url() << url.isValid (); 0457 if (!m_view) return false; 0458 stop (); 0459 Source * src = (url.isEmpty () ? m_sources ["urlsource"] : (!url.scheme().compare ("kmplayer") && m_sources.contains (url.host ()) ? m_sources [url.host ()] : m_sources ["urlsource"])); 0460 setSource (src); 0461 src->setSubURL (QUrl ()); 0462 src->setUrl (url.isLocalFile () ? url.toLocalFile() : url.url ()); 0463 if (src->avoidRedirects ()) 0464 src->activate (); 0465 return true; 0466 } 0467 0468 bool PartBase::openUrl(const QList<QUrl>& urls) { 0469 if (urls.size () == 1) { 0470 openUrl(urls[0]); 0471 } else { 0472 openUrl (QUrl ()); 0473 NodePtr d = m_source->document (); 0474 if (d) 0475 for (int i = 0; i < urls.size (); i++) { 0476 const QUrl &url = urls [i]; 0477 d->appendChild (new GenericURL (d, 0478 url.isLocalFile() ? url.toLocalFile() : url.toString())); 0479 } 0480 } 0481 return true; 0482 } 0483 0484 void PartBase::openUrl (const QUrl &u, const QString &t, const QString &srv) 0485 { 0486 qCDebug(LOG_KMPLAYER_COMMON) << u << " " << t << " " << srv; 0487 QDBusMessage msg = QDBusMessage::createMethodCall ( 0488 "org.kde.klauncher", "/KLauncher", 0489 "org.kde.KLauncher", "start_service_by_desktop_name"); 0490 QStringList urls; 0491 urls << u.url (); 0492 msg << "kfmclient" << urls << QStringList () << QString () << true; 0493 msg.setDelayedReply (false); 0494 QDBusConnection::sessionBus().send (msg); 0495 } 0496 0497 bool PartBase::closeUrl () { 0498 stop (); 0499 if (m_view) 0500 m_view->reset (); 0501 return true; 0502 } 0503 0504 bool PartBase::openFile () { 0505 return false; 0506 } 0507 0508 void PartBase::keepMovieAspect (bool b) { 0509 if (m_view) 0510 m_view->setKeepSizeRatio (b); 0511 } 0512 0513 void PartBase::timerEvent (QTimerEvent * e) { 0514 if (e->timerId () == m_update_tree_timer) { 0515 m_update_tree_timer = 0; 0516 updateTree (m_update_tree_full, true); 0517 } else if (e->timerId () == m_rec_timer) { 0518 m_rec_timer = 0; 0519 if (m_record_doc) 0520 openUrl(QUrl::fromUserInput(convertNode <RecordDocument> (m_record_doc)->record_file)); 0521 } 0522 killTimer (e->timerId ()); 0523 } 0524 0525 void PartBase::playingStarted () { 0526 qCDebug(LOG_KMPLAYER_COMMON) << "playingStarted " << this; 0527 if (m_view) { 0528 m_view->controlPanel ()->setPlaying (true); 0529 m_view->controlPanel ()->showPositionSlider (!!m_source->length ()); 0530 m_view->controlPanel ()->enableSeekButtons (m_source->isSeekable ()); 0531 m_view->playingStart (); 0532 //if (m_settings->autoadjustvolume && m_process) 0533 // m_process->volume(m_view->controlPanel()->volumeBar()->value(),true); 0534 } 0535 Q_EMIT loading (100); 0536 } 0537 0538 void PartBase::slotPlayingStarted () { 0539 playingStarted (); 0540 } 0541 0542 void PartBase::playingStopped () { 0543 qCDebug(LOG_KMPLAYER_COMMON) << "playingStopped " << this; 0544 if (m_view) { 0545 m_view->controlPanel ()->setPlaying (false); 0546 m_view->playingStop (); 0547 m_view->reset (); 0548 } 0549 m_bPosSliderPressed = false; 0550 } 0551 0552 void PartBase::slotPlayingStopped () { 0553 playingStarted (); 0554 } 0555 0556 void PartBase::setPosition (int position, int length) { 0557 if (m_view && !m_bPosSliderPressed) { 0558 if (m_media_manager->processes ().size () > 1) 0559 Q_EMIT positioned (0, 0); 0560 else 0561 Q_EMIT positioned (position, length); 0562 } 0563 } 0564 0565 void PartBase::setLoaded (int percentage) { 0566 Q_EMIT loading (percentage); 0567 } 0568 0569 qlonglong PartBase::position () const { 0570 return m_source ? 100 * m_source->position () : 0; 0571 } 0572 0573 void PartBase::pause () { 0574 NodePtr doc = m_source ? m_source->document () : nullptr; 0575 if (doc) { 0576 Mrl *mrl = nullptr; 0577 NodePtrW cur = m_source->current (); 0578 if (cur) { 0579 mrl = cur->mrl (); 0580 if (mrl && Mrl::WindowMode == mrl->view_mode) 0581 mrl = nullptr; 0582 } 0583 if (doc->state == Node::state_deferred) { 0584 doc->undefer (); 0585 if (cur && mrl && mrl->state == Node::state_deferred) 0586 mrl->undefer (); 0587 } else { 0588 doc->defer (); 0589 if (cur && mrl && mrl->unfinished ()) 0590 mrl->defer (); 0591 } 0592 } 0593 } 0594 0595 void PartBase::back () { 0596 m_source->backward (); 0597 } 0598 0599 void PartBase::forward () { 0600 m_source->forward (); 0601 } 0602 0603 void PartBase::playListItemClicked (const QModelIndex& index) { 0604 if (!index.isValid ()) 0605 return; 0606 PlayListView *pv = qobject_cast <PlayListView *> (sender ()); 0607 if (pv->model ()->rowCount ()) { 0608 if (pv->isExpanded (index)) 0609 pv->setExpanded (index, false); 0610 else 0611 pv->setExpanded (index, true); 0612 } 0613 } 0614 0615 void PartBase::playListItemActivated(const QModelIndex &index) { 0616 if (m_in_update_tree) return; 0617 if (m_view->editMode ()) return; 0618 PlayListView *pv = qobject_cast <PlayListView *> (sender ()); 0619 if (!pv->model ()->parent (index).isValid () && index.row ()) 0620 return; // handled by playListItemClicked 0621 PlayItem *vi = static_cast <PlayItem *> (index.internalPointer ()); 0622 TopPlayItem *ri = vi->rootItem (); 0623 if (vi->node) { 0624 QString src = ri->source; 0625 NodePtrW node = vi->node; 0626 //qCDebug(LOG_KMPLAYER_COMMON) << src << " " << vi->node->nodeName(); 0627 Source * source = src.isEmpty() ? m_source : m_sources[src.toLatin1().constData()]; 0628 if (node->isPlayable () || id_node_playlist_item == node->id) { 0629 source->play (node->mrl ()); //may become !isPlayable by lazy loading 0630 if (node && !node->isPlayable ()) 0631 Q_EMIT treeChanged (ri->id, node, nullptr, false, true); 0632 } // else if (vi->childCount ()) {handled by playListItemClicked 0633 } else if (vi->attribute) { 0634 if (vi->attribute->name () == Ids::attr_src || 0635 vi->attribute->name () == Ids::attr_href || 0636 vi->attribute->name () == Ids::attr_url || 0637 vi->attribute->name () == Ids::attr_value || 0638 vi->attribute->name () == "data") { 0639 QString src (vi->attribute->value ()); 0640 if (!src.isEmpty ()) { 0641 PlayItem *pi = vi->parent (); 0642 if (pi) { 0643 for (Node *e = pi->node.ptr (); e; e = e->parentNode ()) { 0644 Mrl * mrl = e->mrl (); 0645 if (mrl) 0646 src = QUrl (mrl->absolutePath ()).resolved(QUrl(src)).url (); 0647 } 0648 const QUrl url = QUrl::fromUserInput(src); 0649 if (url.isValid ()) 0650 openUrl (url); 0651 } 0652 } 0653 } 0654 } else 0655 Q_EMIT treeChanged (ri->id, ri->node, nullptr, false, false); 0656 if (m_view) 0657 m_view->viewArea ()->setFocus (); 0658 } 0659 0660 void PartBase::updateTree (bool full, bool force) { 0661 if (force) { 0662 m_in_update_tree = true; 0663 if (m_update_tree_full) { 0664 if (m_source) 0665 Q_EMIT treeChanged (0, m_source->root (), m_source->current (), true, false); 0666 } 0667 m_in_update_tree = false; 0668 if (m_update_tree_timer) { 0669 killTimer (m_update_tree_timer); 0670 m_update_tree_timer = 0; 0671 } 0672 } else if (!m_update_tree_timer) { 0673 m_update_tree_timer = startTimer (100); 0674 m_update_tree_full = full; 0675 } else 0676 m_update_tree_full |= full; 0677 } 0678 0679 void PartBase::updateInfo (const QString & msg) { 0680 Q_EMIT infoUpdated (msg); 0681 } 0682 0683 void PartBase::updateStatus (const QString & msg) { 0684 Q_EMIT statusUpdated (msg); 0685 } 0686 0687 void PartBase::setLanguages (const QStringList & al, const QStringList & sl) { 0688 Q_EMIT languagesUpdated (al, sl); 0689 } 0690 0691 void PartBase::audioSelected (QAction* act) { 0692 Q_EMIT panelActionToggled(act); 0693 int i = act->parentWidget()->actions().indexOf(act); 0694 if (i >= 0) 0695 Q_EMIT audioIsSelected (i); 0696 } 0697 0698 void PartBase::subtitleSelected (QAction* act) { 0699 Q_EMIT panelActionToggled(act); 0700 int i = act->parentWidget()->actions().indexOf(act); 0701 if (i >= 0) 0702 Q_EMIT subtitleIsSelected (i); 0703 } 0704 0705 void PartBase::recorderPlaying () { 0706 stop (); 0707 m_view->controlPanel ()->setRecording (true); 0708 Q_EMIT recording (true); 0709 } 0710 0711 void PartBase::recorderStopped () { 0712 stopRecording (); 0713 if (m_view && m_rec_timer < 0 && m_record_doc) 0714 openUrl(QUrl::fromUserInput(convertNode <RecordDocument> (m_record_doc)->record_file)); 0715 } 0716 0717 void PartBase::stopRecording () { 0718 if (m_view) { 0719 m_view->controlPanel ()->setRecording (false); 0720 Q_EMIT recording (false); 0721 if (m_record_doc && m_record_doc->active ()) { 0722 m_record_doc->deactivate (); 0723 if (m_rec_timer > 0) 0724 killTimer (m_rec_timer); 0725 m_rec_timer = 0; 0726 } 0727 } 0728 } 0729 0730 bool PartBase::isRecording () 0731 { 0732 return m_record_doc && m_record_doc->active (); 0733 } 0734 0735 void PartBase::record () { 0736 if (m_view) m_view->setCursor (QCursor (Qt::WaitCursor)); 0737 if (!m_view->controlPanel()->button(ControlPanel::button_record)->isChecked ()) { 0738 stopRecording (); 0739 } else { 0740 m_settings->show ("RecordPage"); 0741 m_view->controlPanel ()->setRecording (false); 0742 } 0743 if (m_view) m_view->setCursor (QCursor (Qt::ArrowCursor)); 0744 } 0745 0746 void PartBase::record (const QString &src, const QString &f, const QString &rec, int auto_start) 0747 { 0748 if (m_record_doc) { 0749 if (m_record_doc->active ()) 0750 m_record_doc->reset (); 0751 m_record_doc->document ()->dispose (); 0752 } 0753 m_record_doc = new RecordDocument (src, f, rec, source ()); 0754 m_record_doc->activate (); 0755 if (auto_start > 0) 0756 m_rec_timer = startTimer (auto_start); 0757 else 0758 m_rec_timer = auto_start; 0759 } 0760 0761 void PartBase::play () { 0762 if (!m_view) 0763 return; 0764 QPushButton *pb = ::qobject_cast <QPushButton *> (sender ()); 0765 if (pb && !pb->isChecked ()) { 0766 stop (); 0767 return; 0768 } 0769 if (m_update_tree_timer) { 0770 killTimer (m_update_tree_timer); 0771 m_update_tree_timer = 0; 0772 } 0773 if (!playing ()) { 0774 PlayItem *lvi = m_view->playList ()->selectedItem (); 0775 if (lvi) { 0776 TopPlayItem *ri = lvi->rootItem (); 0777 if (ri->id != 0) // make sure it's in the first tree 0778 lvi = nullptr; 0779 } 0780 if (!lvi) { 0781 QModelIndex index = m_view->playList ()->model ()->index (0, 0); 0782 lvi = static_cast<PlayItem*>(index.internalPointer ()); 0783 if (!lvi->node) 0784 lvi = nullptr; 0785 } 0786 if (lvi) { 0787 Mrl *mrl = nullptr; 0788 for (Node * n = lvi->node.ptr (); n; n = n->parentNode ()) { 0789 if (n->isPlayable ()) { 0790 mrl = n->mrl (); 0791 break; 0792 } 0793 if (!mrl && n->mrl () && !n->mrl ()->src.isEmpty ()) 0794 mrl = n->mrl (); 0795 } 0796 if (mrl) 0797 m_source->play (mrl); 0798 } 0799 } else { 0800 m_source->play (nullptr); 0801 } 0802 } 0803 0804 bool PartBase::playing () const { 0805 return m_source && m_source->document ()->active (); 0806 } 0807 0808 void PartBase::stop () { 0809 QPushButton * b = m_view ? m_view->controlPanel ()->button (ControlPanel::button_stop) : nullptr; 0810 if (b) { 0811 if (!b->isChecked ()) 0812 b->toggle (); 0813 m_view->setCursor (QCursor (Qt::WaitCursor)); 0814 } 0815 if (m_source) 0816 m_source->reset (); 0817 MediaManager::ProcessInfoMap &pi = m_media_manager->processInfos (); 0818 const MediaManager::ProcessInfoMap::const_iterator ie = pi.constEnd(); 0819 for (MediaManager::ProcessInfoMap::const_iterator i = pi.constBegin(); i != ie; ++i) 0820 i.value ()->quitProcesses (); 0821 MediaManager::ProcessList &processes = m_media_manager->processes (); 0822 const MediaManager::ProcessList::const_iterator e = processes.constEnd(); 0823 for (MediaManager::ProcessList::const_iterator i = processes.constBegin(); i != e; ++i) 0824 (*i)->quit (); 0825 if (m_view) { 0826 m_view->setCursor (QCursor (Qt::ArrowCursor)); 0827 if (b->isChecked ()) 0828 b->toggle (); 0829 m_view->controlPanel ()->setPlaying (false); 0830 setLoaded (100); 0831 updateStatus (i18n ("Ready")); 0832 } 0833 playingStopped (); 0834 } 0835 0836 void PartBase::seek (qlonglong msec) { 0837 if (m_media_manager->processes ().size () == 1) 0838 m_media_manager->processes ().first ()->seek (msec/100, true); 0839 } 0840 0841 void PartBase::adjustVolume (int incdec) { 0842 if (m_media_manager->processes ().size () > 0) 0843 m_media_manager->processes ().first ()->volume (incdec, false); 0844 } 0845 0846 void PartBase::increaseVolume () { 0847 /*if (m_view) 0848 m_view->controlPanel ()->volumeBar ()->setValue (m_view->controlPanel ()->volumeBar ()->value () + 2);*/ 0849 } 0850 0851 void PartBase::decreaseVolume () { 0852 //if (m_view) 0853 // m_view->controlPanel ()->volumeBar ()->setValue (m_view->controlPanel ()->volumeBar ()->value () - 2); 0854 } 0855 0856 void PartBase::posSliderPressed () { 0857 m_bPosSliderPressed=true; 0858 } 0859 0860 void PartBase::posSliderReleased () { 0861 m_bPosSliderPressed=false; 0862 const QSlider * posSlider = ::qobject_cast<const QSlider *> (sender ()); 0863 if (m_media_manager->processes ().size () == 1) 0864 m_media_manager->processes ().first ()->seek (posSlider->value(), true); 0865 } 0866 0867 void PartBase::volumeChanged (int val) { 0868 if (m_media_manager->processes ().size () > 0) { 0869 m_settings->volume = val; 0870 m_media_manager->processes ().first ()->volume (val, true); 0871 } 0872 } 0873 0874 void PartBase::contrastValueChanged (int val) { 0875 if (m_media_manager->processes ().size () > 0) 0876 m_media_manager->processes ().first ()->contrast (val, true); 0877 } 0878 0879 void PartBase::brightnessValueChanged (int val) { 0880 if (m_media_manager->processes ().size () > 0) 0881 m_media_manager->processes ().first ()->brightness (val, true); 0882 } 0883 0884 void PartBase::hueValueChanged (int val) { 0885 if (m_media_manager->processes ().size () > 0) 0886 m_media_manager->processes ().first ()->hue (val, true); 0887 } 0888 0889 void PartBase::saturationValueChanged (int val) { 0890 m_settings->saturation = val; 0891 if (m_media_manager->processes ().size () > 0) 0892 m_media_manager->processes ().first ()->saturation (val, true); 0893 } 0894 0895 void PartBase::sourceHasChangedAspects () { 0896 Q_EMIT sourceDimensionChanged (); 0897 } 0898 0899 void PartBase::positionValueChanged (int pos) { 0900 QSlider * slider = ::qobject_cast <QSlider *> (sender ()); 0901 if (m_media_manager->processes ().size () == 1 && 0902 slider && slider->isEnabled ()) 0903 m_media_manager->processes ().first ()->seek (pos, true); 0904 } 0905 0906 void PartBase::fullScreen () { 0907 if (m_view) 0908 m_view->fullScreen (); 0909 } 0910 0911 void PartBase::toggleFullScreen () { 0912 m_view->fullScreen (); 0913 } 0914 0915 bool PartBase::isPlaying () { 0916 return playing (); 0917 } 0918 0919 KAboutData* PartBase::createAboutData () { 0920 KMessageBox::error(nullptr, "createAboutData", "KMPlayer"); 0921 return nullptr; 0922 } 0923 0924 //----------------------------------------------------------------------------- 0925 0926 SourceDocument::SourceDocument (Source *s, const QString &url) 0927 : Document (url, s), m_source (s) {} 0928 0929 void SourceDocument::message (MessageType msg, void *data) { 0930 switch (msg) { 0931 0932 case MsgInfoString: { 0933 QString info (data ? *((QString *) data) : QString ()); 0934 m_source->player ()->updateInfo (info); 0935 return; 0936 } 0937 0938 case MsgAccessKey: 0939 for (Connection *c = m_KeyListeners.first(); c; c = m_KeyListeners.next ()) 0940 if (c->payload && c->connecter) { 0941 KeyLoad *load = (KeyLoad *) c->payload; 0942 if (load->key == (int) (long) data) 0943 post (c->connecter, new Posting (this, MsgAccessKey)); 0944 } 0945 return; 0946 0947 default: 0948 break; 0949 } 0950 Document::message (msg, data); 0951 } 0952 0953 void *SourceDocument::role (RoleType msg, void *data) { 0954 switch (msg) { 0955 0956 case RoleMediaManager: 0957 return m_source->player ()->mediaManager (); 0958 0959 case RoleChildDisplay: { 0960 PartBase *p = m_source->player (); 0961 if (p->view ()) 0962 return p->viewWidget ()->viewArea ()->getSurface ((Mrl *) data); 0963 return nullptr; 0964 } 0965 0966 case RoleReceivers: 0967 0968 switch ((MessageType) (long) data) { 0969 0970 case MsgAccessKey: 0971 return &m_KeyListeners; 0972 0973 case MsgSurfaceUpdate: { 0974 PartBase *p = m_source->player (); 0975 if (p->view ()) 0976 return p->viewWidget ()->viewArea ()->updaters (); 0977 } 0978 // fall through 0979 0980 default: 0981 break; 0982 } 0983 // fall through 0984 0985 default: 0986 break; 0987 } 0988 return Document::role (msg, data); 0989 } 0990 0991 0992 Source::Source (const QString&, PartBase * player, const char * n) 0993 : QObject (player), 0994 m_name (n), m_player (player), 0995 m_identified (false), m_auto_play (true), m_avoid_redirects (false), 0996 m_frequency (0), m_xvport (0), m_xvencoding (-1), m_doc_timer (0) { 0997 init (); 0998 } 0999 1000 Source::~Source () { 1001 if (m_document) 1002 m_document->document ()->dispose (); 1003 m_document = nullptr; 1004 } 1005 1006 void Source::init () { 1007 //setDimensions (320, 240); 1008 m_width = 0; 1009 m_height = 0; 1010 m_aspect = 0.0; 1011 m_length = 0; 1012 m_audio_id = -1; 1013 m_subtitle_id = -1; 1014 m_position = 0; 1015 setLength (m_document, 0); 1016 m_recordcmd.truncate (0); 1017 } 1018 1019 void Source::setLanguages (LangInfoPtr audio, LangInfoPtr sub) 1020 { 1021 m_audio_infos = audio; 1022 m_subtitle_infos = sub; 1023 1024 QStringList alst; 1025 QStringList slst; 1026 for (LangInfoPtr li = audio; li; li = li->next) 1027 alst.push_back (li->name); 1028 for (LangInfoPtr li = sub; li; li = li->next) 1029 slst.push_back (li->name); 1030 1031 m_player->setLanguages (alst, slst); 1032 } 1033 1034 void Source::setDimensions (NodePtr node, int w, int h) { 1035 Mrl *mrl = node ? node->mrl () : nullptr; 1036 if (mrl) { 1037 float a = h > 0 ? 1.0 * w / h : 0.0; 1038 mrl->size = SSize (w, h); 1039 mrl->aspect = a; 1040 bool ev = (w > 0 && h > 0) || 1041 (h == 0 && m_height > 0) || 1042 (w == 0 && m_width > 0); 1043 if (Mrl::SingleMode == mrl->view_mode) { 1044 m_width = w; 1045 m_height = h; 1046 } 1047 if (Mrl::WindowMode == mrl->view_mode || m_aspect < 0.001) 1048 setAspect (node, h > 0 ? 1.0 * w / h : 0.0); 1049 //qCDebug(LOG_KMPLAYER_COMMON) << "setDimensions " << w << "x" << h << " a:" << m_aspect; 1050 else if (ev) 1051 Q_EMIT dimensionsChanged (); 1052 } 1053 } 1054 1055 void Source::setAspect (NodePtr node, float a) { 1056 //qCDebug(LOG_KMPLAYER_COMMON) << "setAspect " << a; 1057 Mrl *mrl = node ? node->mrl () : nullptr; 1058 bool changed = false; 1059 if (mrl && 1060 mrl->media_info && 1061 mrl->media_info->media && 1062 MediaManager::AudioVideo == mrl->media_info->type) { 1063 static_cast <AudioVideoMedia*>(mrl->media_info->media)->viewer ()->setAspect(a); 1064 if (mrl->view_mode == Mrl::WindowMode) 1065 changed |= (fabs (mrl->aspect - a) > 0.001); 1066 mrl->aspect = a; 1067 } 1068 if (!mrl || mrl->view_mode == Mrl::SingleMode) { 1069 changed |= (fabs (m_aspect - a) > 0.001); 1070 m_aspect = a; 1071 if (changed && m_player->view ()) 1072 m_player->viewWidget ()->viewArea ()->resizeEvent (nullptr); 1073 1074 } else { 1075 mrl->message (MsgSurfaceBoundsUpdate); 1076 } 1077 if (changed) 1078 Q_EMIT dimensionsChanged (); 1079 } 1080 1081 void Source::setLength (NodePtr, int len) { 1082 m_length = len; 1083 m_player->setPosition (m_position, m_length); 1084 } 1085 1086 void Source::setPosition (int pos) { 1087 m_position = pos; 1088 m_player->setPosition (pos, m_length); 1089 } 1090 1091 void Source::setLoading (int percentage) { 1092 m_player->setLoaded (percentage); 1093 } 1094 1095 /* 1096 static void printTree (NodePtr root, QString off=QString()) { 1097 if (!root) { 1098 qCDebug(LOG_KMPLAYER_COMMON) << off << "[null]"; 1099 return; 1100 } 1101 qCDebug(LOG_KMPLAYER_COMMON) << off << root->nodeName() << " " << (Element*)root << (root->isPlayable() ? root->mrl ()->src : QString ("-")); 1102 off += QString (" "); 1103 for (NodePtr e = root->firstChild(); e; e = e->nextSibling()) 1104 printTree(e, off); 1105 }*/ 1106 1107 void Source::setUrl (const QString &url) { 1108 qCDebug(LOG_KMPLAYER_COMMON) << url; 1109 m_url = QUrl::fromUserInput(url); 1110 if (m_document && !m_document->hasChildNodes () && 1111 (m_document->mrl()->src.isEmpty () || 1112 m_document->mrl()->src == url)) 1113 // special case, mime is set first by plugin FIXME v 1114 m_document->mrl()->src = url; 1115 else { 1116 if (m_document) 1117 m_document->document ()->dispose (); 1118 m_document = new SourceDocument (this, url); 1119 } 1120 if (m_player->source () == this) 1121 m_player->updateTree (); 1122 1123 QTimer::singleShot (0, this, &Source::changedUrl); 1124 } 1125 1126 void Source::changedUrl() 1127 { 1128 Q_EMIT titleChanged (this->prettyName ()); 1129 } 1130 1131 void Source::setTitle (const QString & title) { 1132 Q_EMIT titleChanged (title); 1133 } 1134 1135 void Source::setAudioLang (int id) { 1136 LangInfoPtr li = m_audio_infos; 1137 for (; id > 0 && li; li = li->next) 1138 id--; 1139 m_audio_id = li ? li->id : -1; 1140 if (m_player->view () && m_player->mediaManager ()->processes ().size ()) 1141 m_player->mediaManager ()->processes ().first ()->setAudioLang (m_audio_id); 1142 } 1143 1144 void Source::setSubtitle (int id) { 1145 LangInfoPtr li = m_subtitle_infos; 1146 for (; id > 0 && li; li = li->next) 1147 id--; 1148 m_subtitle_id = li ? li->id : -1; 1149 if (m_player->view () && m_player->mediaManager ()->processes ().size ()) 1150 m_player->mediaManager ()->processes ().first ()->setSubtitle (m_subtitle_id); 1151 } 1152 1153 void Source::reset () { 1154 if (m_document) { 1155 qCDebug(LOG_KMPLAYER_COMMON) << "Source::reset " << name () << endl; 1156 NodePtr doc = m_document; // avoid recursive calls 1157 m_document = nullptr; 1158 doc->reset (); 1159 m_document = doc; 1160 m_player->updateTree (); 1161 } 1162 init (); 1163 } 1164 1165 void Source::play (Mrl *mrl) { 1166 if (!mrl) 1167 mrl = document ()->mrl (); 1168 NodePtrW guarded = mrl; 1169 blockSignals (true); //endOfPlayItems, but what is hyperspace? 1170 document ()->reset (); 1171 blockSignals (false); 1172 mrl = guarded ? guarded->mrl () : m_document->mrl (); 1173 if (!mrl) 1174 return; 1175 m_width = m_height = 0; 1176 m_player->changeURL (mrl->src); 1177 for (Node *p = mrl->parentNode(); p; p = p->parentNode()) 1178 p->state = Element::state_activated; 1179 mrl->activate (); 1180 m_width = mrl->size.width; 1181 m_height = mrl->size.height; 1182 m_aspect = mrl->aspect; 1183 //qCDebug(LOG_KMPLAYER_COMMON) << "Source::playCurrent " << (m_current ? m_current->nodeName():" doc act:") << (m_document && !m_document->active ()) << " cur:" << (!m_current) << " cur act:" << (m_current && !m_current->active ()); 1184 m_player->updateTree (); 1185 Q_EMIT dimensionsChanged (); 1186 } 1187 1188 bool Source::authoriseUrl (const QString &) { 1189 return true; 1190 } 1191 1192 void Source::setTimeout (int ms) { 1193 //qCDebug(LOG_KMPLAYER_COMMON) << "Source::setTimeout " << ms; 1194 if (m_doc_timer) 1195 killTimer (m_doc_timer); 1196 m_doc_timer = ms > -1 ? startTimer (ms) : 0; 1197 } 1198 1199 void Source::timerEvent (QTimerEvent * e) { 1200 if (e->timerId () == m_doc_timer && m_document && m_document->active ()) 1201 m_document->document ()->timer (); // will call setTimeout() 1202 else 1203 killTimer (e->timerId ()); 1204 } 1205 1206 void Source::setCurrent (Mrl *mrl) { 1207 m_current = mrl; 1208 m_width = mrl->size.width; 1209 m_height = mrl->size.height; 1210 m_aspect = mrl->aspect; 1211 } 1212 1213 void Source::stateElementChanged (Node *elm, Node::State os, Node::State ns) { 1214 //qCDebug(LOG_KMPLAYER_COMMON) << "[01;31mSource::stateElementChanged[00m " << elm->nodeName () << " state:" << (int) elm->state << " cur isPlayable:" << (m_current && m_current->isPlayable ()) << " elm==linkNode:" << (m_current && elm == m_current->mrl ()->linkNode ()) << endl; 1215 if (ns == Node::state_activated && 1216 elm->mrl ()) { 1217 if (Mrl::WindowMode != elm->mrl ()->view_mode && 1218 (!elm->parentNode () || 1219 !elm->parentNode ()->mrl () || 1220 Mrl::WindowMode != elm->parentNode ()->mrl ()->view_mode)) 1221 setCurrent (elm->mrl ()); 1222 if (m_current.ptr () == elm) 1223 Q_EMIT startPlaying (); 1224 } else if (ns == Node::state_deactivated) { 1225 if (elm == m_document) { 1226 NodePtrW guard = elm; 1227 Q_EMIT endOfPlayItems (); // played all items FIXME on jumps 1228 if (!guard) 1229 return; 1230 } else if (m_current.ptr () == elm) { 1231 Q_EMIT stopPlaying (); 1232 } 1233 } 1234 if (elm->role (RolePlaylist)) { 1235 if (ns == Node::state_activated || ns == Node::state_deactivated) 1236 m_player->updateTree (); 1237 else if (ns == Node::state_began || os == Node::state_began) 1238 m_player->updateTree (false); 1239 } 1240 } 1241 1242 void Source::bitRates (int & preferred, int & maximal) { 1243 preferred = 1024 * m_player->settings ()->prefbitrate; 1244 maximal= 1024 * m_player->settings ()->maxbitrate; 1245 } 1246 1247 void Source::openUrl (const QUrl &url, const QString &t, const QString &srv) { 1248 m_player->openUrl (url, t, srv); 1249 } 1250 1251 void Source::enableRepaintUpdaters (bool enable, unsigned int off_time) { 1252 if (m_player->view ()) 1253 m_player->viewWidget ()->viewArea()->enableUpdaters (enable, off_time); 1254 } 1255 1256 void Source::insertURL (NodePtr node, const QString & mrl, const QString & title) { 1257 if (!node || !node->mrl ()) // this should always be false 1258 return; 1259 QString cur_url = node->mrl ()->absolutePath (); 1260 const QUrl url = QUrl(cur_url).resolved(QUrl(mrl)); 1261 QString urlstr = QUrl::fromPercentEncoding (url.url ().toUtf8 ()); 1262 qCDebug(LOG_KMPLAYER_COMMON) << cur_url << " " << urlstr; 1263 if (!url.isValid ()) 1264 qCCritical(LOG_KMPLAYER_COMMON) << "try to append non-valid url" << endl; 1265 else if (QUrl::fromPercentEncoding (cur_url.toUtf8 ()) == urlstr) 1266 qCCritical(LOG_KMPLAYER_COMMON) << "try to append url to itself" << endl; 1267 else { 1268 int depth = 0; // cache this? 1269 for (Node *e = node; e->parentNode (); e = e->parentNode ()) 1270 ++depth; 1271 if (depth < 40) { 1272 node->appendChild (new GenericURL (m_document, urlstr, title.isEmpty() ? QUrl::fromPercentEncoding (mrl.toUtf8 ()) : title)); 1273 m_player->updateTree (); 1274 } else 1275 qCCritical(LOG_KMPLAYER_COMMON) << "insertURL exceeds depth limit" << endl; 1276 } 1277 } 1278 1279 void Source::backward () { 1280 Node *back = m_current ? m_current.ptr () : m_document.ptr (); 1281 while (back && back != m_document.ptr ()) { 1282 if (back->previousSibling ()) { 1283 back = back->previousSibling (); 1284 while (!back->isPlayable () && back->lastChild ()) 1285 back = back->lastChild (); 1286 if (back->isPlayable () && !back->active ()) { 1287 play (back->mrl ()); 1288 break; 1289 } 1290 } else { 1291 back = back->parentNode(); 1292 } 1293 } 1294 } 1295 1296 void Source::forward () { 1297 if (m_current) 1298 m_current->finish (); 1299 if (m_document && !m_document->active ()) 1300 play (m_document->mrl ()); 1301 } 1302 1303 void Source::setDocument (KMPlayer::NodePtr doc, KMPlayer::NodePtr cur) { 1304 if (m_document) 1305 m_document->document()->dispose (); 1306 m_document = doc; 1307 setCurrent (cur->mrl ()); 1308 //qCDebug(LOG_KMPLAYER_COMMON) << "setDocument: " << m_document->outerXML (); 1309 } 1310 1311 NodePtr Source::document () { 1312 if (!m_document) 1313 m_document = new SourceDocument (this, QString ()); 1314 return m_document; 1315 } 1316 1317 NodePtr Source::root () { 1318 return document (); 1319 } 1320 1321 bool Source::processOutput (const QString &) { 1322 return false; 1323 } 1324 1325 QString Source::filterOptions () { 1326 Settings* m_settings = m_player->settings (); 1327 QString PPargs (""); 1328 if (m_settings->postprocessing) 1329 { 1330 if (m_settings->pp_default) 1331 PPargs = "-vf pp=de"; 1332 else if (m_settings->pp_fast) 1333 PPargs = "-vf pp=fa"; 1334 else if (m_settings->pp_custom) { 1335 PPargs = "-vf pp="; 1336 if (m_settings->pp_custom_hz) { 1337 PPargs += "hb"; 1338 if (m_settings->pp_custom_hz_aq && \ 1339 m_settings->pp_custom_hz_ch) 1340 PPargs += ":ac"; 1341 else if (m_settings->pp_custom_hz_aq) 1342 PPargs += ":a"; 1343 else if (m_settings->pp_custom_hz_ch) 1344 PPargs += ":c"; 1345 PPargs += '/'; 1346 } 1347 if (m_settings->pp_custom_vt) { 1348 PPargs += "vb"; 1349 if (m_settings->pp_custom_vt_aq && \ 1350 m_settings->pp_custom_vt_ch) 1351 PPargs += ":ac"; 1352 else if (m_settings->pp_custom_vt_aq) 1353 PPargs += ":a"; 1354 else if (m_settings->pp_custom_vt_ch) 1355 PPargs += ":c"; 1356 PPargs += '/'; 1357 } 1358 if (m_settings->pp_custom_dr) { 1359 PPargs += "dr"; 1360 if (m_settings->pp_custom_dr_aq && \ 1361 m_settings->pp_custom_dr_ch) 1362 PPargs += ":ac"; 1363 else if (m_settings->pp_custom_dr_aq) 1364 PPargs += ":a"; 1365 else if (m_settings->pp_custom_dr_ch) 1366 PPargs += ":c"; 1367 PPargs += '/'; 1368 } 1369 if (m_settings->pp_custom_al) { 1370 PPargs += "al"; 1371 if (m_settings->pp_custom_al_f) 1372 PPargs += ":f"; 1373 PPargs += '/'; 1374 } 1375 if (m_settings->pp_custom_tn) { 1376 PPargs += "tn"; 1377 /*if (1 <= m_settings->pp_custom_tn_s <= 3){ 1378 PPargs += ":"; 1379 PPargs += m_settings->pp_custom_tn_s; 1380 }*/ //disabled 'cos this is wrong 1381 PPargs += '/'; 1382 } 1383 if (m_settings->pp_lin_blend_int) { 1384 PPargs += "lb"; 1385 PPargs += '/'; 1386 } 1387 if (m_settings->pp_lin_int) { 1388 PPargs += "li"; 1389 PPargs += '/'; 1390 } 1391 if (m_settings->pp_cub_int) { 1392 PPargs += "ci"; 1393 PPargs += '/'; 1394 } 1395 if (m_settings->pp_med_int) { 1396 PPargs += "md"; 1397 PPargs += '/'; 1398 } 1399 if (m_settings->pp_ffmpeg_int) { 1400 PPargs += "fd"; 1401 PPargs += '/'; 1402 } 1403 } 1404 if (PPargs.endsWith("/")) 1405 PPargs.truncate(PPargs.size ()-1); 1406 } 1407 return PPargs; 1408 } 1409 1410 bool Source::hasLength () { 1411 return true; 1412 } 1413 1414 bool Source::isSeekable () { 1415 return true; 1416 } 1417 1418 void Source::setIdentified (bool b) { 1419 //qCDebug(LOG_KMPLAYER_COMMON) << "Source::setIdentified " << m_identified << b; 1420 m_identified = b; 1421 if (!b) { 1422 m_audio_infos = nullptr; 1423 m_subtitle_infos = nullptr; 1424 } 1425 } 1426 1427 QString Source::plugin (const QString &mime) const { 1428 return KConfigGroup (m_player->config (), mime).readEntry ("plugin", QString ()); 1429 } 1430 1431 QString Source::prettyName () { 1432 return i18n ("Unknown"); 1433 } 1434 1435 void Source::slotActivate () 1436 { 1437 activate (); 1438 } 1439 1440 //----------------------------------------------------------------------------- 1441 1442 URLSource::URLSource (PartBase * player, const QUrl & url) 1443 : Source (i18n ("URL"), player, "urlsource"), activated (false) { 1444 setUrl (url.url ()); 1445 //qCDebug(LOG_KMPLAYER_COMMON) << "URLSource::URLSource"; 1446 } 1447 1448 URLSource::~URLSource () { 1449 //qCDebug(LOG_KMPLAYER_COMMON) << "URLSource::~URLSource"; 1450 } 1451 1452 void URLSource::init () { 1453 Source::init (); 1454 } 1455 1456 void URLSource::dimensions (int & w, int & h) { 1457 if (!m_player->mayResize () && m_player->view ()) { 1458 w = static_cast <View *> (m_player->view ())->viewArea ()->width (); 1459 h = static_cast <View *> (m_player->view ())->viewArea ()->height (); 1460 } else { 1461 Source::dimensions (w, h); 1462 } 1463 } 1464 1465 bool URLSource::hasLength () { 1466 return !!length (); 1467 } 1468 1469 void URLSource::activate () { 1470 if (activated) 1471 return; 1472 activated = true; 1473 if (url ().isEmpty () && (!m_document || !m_document->hasChildNodes ())) { 1474 m_player->updateTree (); 1475 return; 1476 } 1477 if (m_auto_play) 1478 play (nullptr); 1479 } 1480 1481 void URLSource::reset () { 1482 Source::reset (); 1483 } 1484 1485 void URLSource::forward () { 1486 Source::forward (); 1487 } 1488 1489 void URLSource::backward () { 1490 Source::backward (); 1491 } 1492 1493 void URLSource::play (Mrl *mrl) { 1494 Source::play (mrl); 1495 } 1496 1497 void URLSource::deactivate () { 1498 if (!activated) 1499 return; 1500 activated = false; 1501 reset (); 1502 if (m_document) { 1503 m_document->document ()->dispose (); 1504 m_document = nullptr; 1505 } 1506 if (m_player->view ()) 1507 m_player->viewWidget ()->viewArea ()->getSurface (nullptr); 1508 } 1509 1510 QString URLSource::prettyName () { 1511 if (m_url.isEmpty ()) 1512 return i18n ("URL"); 1513 if (m_url.url ().size () > 50) { 1514 QString newurl; 1515 if (!m_url.isLocalFile ()) { 1516 newurl = m_url.scheme() + QString ("://"); 1517 if (!m_url.host().isEmpty()) 1518 newurl += m_url.host (); 1519 if (m_url.port () != -1) 1520 newurl += QString (":%1").arg (m_url.port ()); 1521 } 1522 QString file = m_url.fileName (); 1523 int len = newurl.size () + file.size (); 1524 QUrl path = m_url.adjusted(QUrl::RemoveFilename|QUrl::RemoveQuery|QUrl::RemoveFragment); 1525 bool modified = false; 1526 while (path.url ().size () + len > 50) { 1527 const QUrl upPath = KIO::upUrl(path); 1528 if (path == upPath) { 1529 break; 1530 } 1531 path = upPath; 1532 modified = true; 1533 } 1534 QString dir = path.path (); 1535 if (!dir.endsWith (QString ("/"))) 1536 dir += '/'; 1537 if (modified) 1538 dir += QString (".../"); 1539 newurl += dir + file; 1540 return i18n ("URL - ") + newurl; 1541 } 1542 if (m_url.isLocalFile()) 1543 return i18n ("URL - ") + m_url.toLocalFile(); 1544 return i18n ("URL - ") + m_url.toDisplayString(); 1545 } 1546 1547 bool URLSource::authoriseUrl (const QString &url) { 1548 const QUrl base = QUrl::fromUserInput(document ()->mrl ()->src); 1549 const QUrl dest = QUrl::fromUserInput(url); 1550 if (base != dest) { 1551 // check if some remote playlist tries to open something local, but 1552 // do ignore unknown protocols because there are so many and we only 1553 // want to cache local ones. 1554 if ( 1555 #if 0 1556 !KProtocolInfo::protocolClass (dest.scheme()).isEmpty () && 1557 #else 1558 dest.isLocalFile () && 1559 #endif 1560 !KUrlAuthorized::authorizeUrlAction ("redirect", base, dest)) { 1561 qCWarning(LOG_KMPLAYER_COMMON) << "requestPlayURL from document " << base << " to play " << dest << " is not allowed"; 1562 return false; 1563 } 1564 } 1565 return Source::authoriseUrl (url); 1566 } 1567 1568 void URLSource::setUrl (const QString &url) { 1569 Source::setUrl (url); 1570 Mrl *mrl = document ()->mrl (); 1571 if (!url.isEmpty () && m_url.isLocalFile () && mrl->mimetype.isEmpty ()) { 1572 const QMimeType mimeType = QMimeDatabase().mimeTypeForUrl(m_url); 1573 if (mimeType.isValid()) 1574 mrl->mimetype = mimeType.name(); 1575 } 1576 } 1577 1578 //----------------------------------------------------------------------------- 1579 1580 #include "moc_kmplayerpartbase.cpp"