File indexing completed on 2024-04-21 04:54:16
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 "kmplayer_part.h" 0008 0009 #include <list> 0010 #include <algorithm> 0011 0012 #include <QLabel> 0013 #include <QMenu> 0014 #include <QTimer> 0015 #include <QPushButton> 0016 #include <QSlider> 0017 #include <QStatusBar> 0018 #include <QFile> 0019 #include <QMetaObject> 0020 #include <QStandardPaths> 0021 0022 class KXMLGUIClient; // workaround for kde3.3 on sarge with gcc4, kactioncollection.h does not forward declare KXMLGUIClient 0023 #include <KConfig> 0024 #include <KUrlAuthorized> 0025 #include <KIconLoader> 0026 #include <KLocalizedString> 0027 #if KCOREADDONS_VERSION >= QT_VERSION_CHECK(5, 77, 0) 0028 #include <KPluginMetaData> 0029 #endif 0030 #include <KIO/Job> 0031 0032 #include "kmplayerpart_log.h" 0033 #include "kmplayerview.h" 0034 #include "playlistview.h" 0035 #include "kmplayercontrolpanel.h" 0036 #include "kmplayerconfig.h" 0037 #include "kmplayerprocess.h" 0038 #include "viewarea.h" 0039 0040 #include <cstdlib> 0041 #include <unistd.h> // unlink, getpid 0042 0043 using namespace KMPlayer; 0044 0045 typedef std::list <KMPlayerPart *> KMPlayerPartList; 0046 0047 class KMPlayerPartStatic : public GlobalShared<KMPlayerPartStatic> 0048 { 0049 public: 0050 KMPlayerPartStatic (KMPlayerPartStatic **); 0051 ~KMPlayerPartStatic () override; 0052 KMPlayerPartList partlist; 0053 int counter; 0054 }; 0055 0056 static KMPlayerPartStatic * kmplayerpart_static = nullptr; 0057 0058 KMPlayerPartStatic::KMPlayerPartStatic (KMPlayerPartStatic **glob) : GlobalShared<KMPlayerPartStatic> (glob), counter (0) { 0059 Ids::init (); 0060 } 0061 0062 KMPlayerPartStatic::~KMPlayerPartStatic () { 0063 kmplayerpart_static = nullptr; 0064 Ids::reset (); 0065 // delete map content 0066 } 0067 0068 struct GroupPredicate 0069 { 0070 const KMPlayerPart * m_part; 0071 const QString & m_group; 0072 bool m_get_any; 0073 GroupPredicate(const KMPlayerPart *part, const QString &group, bool b=false) 0074 : m_part (part), m_group (group), m_get_any (b) {} 0075 bool operator () (const KMPlayerPart * part) const { 0076 return ((m_get_any && part != m_part && 0077 !part->master () && !part->url ().isEmpty ()) || 0078 (m_part->allowRedir (part->docBase ()) && 0079 (part->m_group == m_group || 0080 part->m_group == QString::fromLatin1("_master") || 0081 m_group == QString::fromLatin1("_master")) && 0082 (part->m_features & KMPlayerPart::Feat_Viewer) != 0083 (m_part->m_features & KMPlayerPart::Feat_Viewer))); 0084 } 0085 }; 0086 0087 //----------------------------------------------------------------------------- 0088 0089 #if KCOREADDONS_VERSION < QT_VERSION_CHECK(5, 77, 0) 0090 KAboutData* KMPlayerFactory::s_about = nullptr; 0091 #endif 0092 0093 KMPlayerFactory::KMPlayerFactory () { 0094 } 0095 0096 KMPlayerFactory::~KMPlayerFactory () { 0097 } 0098 0099 #if KCOREADDONS_VERSION < QT_VERSION_CHECK(5, 77, 0) 0100 KAboutData& KMPlayerFactory::aboutData() { 0101 if (!s_about) { 0102 s_about = new KAboutData("kmplayer", i18n("KMPlayer"), QStringLiteral(KMPLAYER_VERSION_STRING), 0103 i18n("Embedded MPlayer by KDE"), 0104 KAboutLicense::LGPL); 0105 s_about->addAuthor(QStringLiteral("Koos Vriezen"), QString(), "koos.vriezen@gmail.com"); 0106 } 0107 return *s_about; 0108 } 0109 #endif 0110 0111 QObject* KMPlayerFactory::create(const char *iface, QWidget* parentWidget, QObject* parent, 0112 const QVariantList& args, const QString&) 0113 { 0114 Q_UNUSED(iface) 0115 #if KCOREADDONS_VERSION >= QT_VERSION_CHECK(5, 77, 0) 0116 return new KMPlayerPart(parentWidget, parent, metaData(), args); 0117 #else 0118 return new KMPlayerPart(parentWidget, parent, args); 0119 #endif 0120 } 0121 0122 //----------------------------------------------------------------------------- 0123 0124 GrabDocument::GrabDocument (KMPlayerPart *part, const QString &url, 0125 const QString &file, PlayListNotify *) 0126 : SourceDocument (part->sources () ["urlsource"], url), 0127 m_grab_file (file), 0128 m_part (part) { 0129 id = id_node_grab_document; 0130 resolved = true; 0131 } 0132 0133 void GrabDocument::activate () { 0134 media_info = new MediaInfo (this, MediaManager::AudioVideo); 0135 media_info->create (); 0136 qCDebug(LOG_KMPLAYER_PART) << src; 0137 Mrl::activate (); 0138 } 0139 0140 void GrabDocument::undefer () { 0141 begin (); 0142 } 0143 0144 void GrabDocument::begin () { 0145 setState (state_began); 0146 AudioVideoMedia *av = static_cast <AudioVideoMedia *> (media_info->media); 0147 qCDebug(LOG_KMPLAYER_PART) << m_grab_file; 0148 av->grabPicture (m_grab_file, 0); 0149 } 0150 0151 void GrabDocument::message (MessageType msg, void *content) { 0152 if (MsgMediaFinished == msg) { 0153 state = state_finished; 0154 m_part->startUrl (QUrl (), m_grab_file); 0155 // deleted here by Source::reset 0156 } else { 0157 SourceDocument::message (msg, content); 0158 } 0159 } 0160 0161 //----------------------------------------------------------------------------- 0162 0163 static bool getBoolValue (const QString & value) { 0164 return (value.toLower() != QString::fromLatin1("false") && 0165 value.toLower() != QString::fromLatin1("off") && 0166 value.toLower() != QString::fromLatin1("0")); 0167 } 0168 0169 #define SET_FEAT_ON(f) { m_features |= f; turned_off_features &= ~f; } 0170 #define SET_FEAT_OFF(f) { m_features &= ~f; turned_off_features |= f; } 0171 0172 #if KCOREADDONS_VERSION >= QT_VERSION_CHECK(5, 77, 0) 0173 KMPlayerPart::KMPlayerPart(QWidget* wparent, QObject* ppart, const KPluginMetaData& metaData, const QVariantList &args) 0174 #else 0175 KMPlayerPart::KMPlayerPart (QWidget *wparent, 0176 QObject* ppart, const QVariantList& args) 0177 #endif 0178 : PartBase (wparent, ppart, KSharedConfig::openConfig ("kmplayerrc")), 0179 m_master (nullptr), 0180 m_browserextension (new KMPlayerBrowserExtension (this)), 0181 m_liveconnectextension (new KMPlayerLiveConnectExtension (this)), 0182 m_playtime_info(nullptr), 0183 m_expected_view_width (0), 0184 m_expected_view_height (0), 0185 m_features (Feat_Unknown), 0186 m_started_emited (false), 0187 m_wait_npp_loaded (false) 0188 { 0189 #if KCOREADDONS_VERSION >= QT_VERSION_CHECK(5, 77, 0) 0190 setMetaData(metaData); 0191 #else 0192 setComponentData(KMPlayerFactory::aboutData()); 0193 #endif 0194 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerPart(" << this << ")::KMPlayerPart ()"; 0195 bool show_fullscreen = false; 0196 if (!kmplayerpart_static) 0197 (void) new KMPlayerPartStatic (&kmplayerpart_static); 0198 else 0199 kmplayerpart_static->ref (); 0200 init (actionCollection (), 0201 QString ("/KMPlayerPart%1").arg(kmplayerpart_static->counter++), true); 0202 createBookmarkMenu (m_view->controlPanel ()->bookmarkMenu, actionCollection ()); 0203 m_view->controlPanel ()->bookmarkAction->setVisible (true); 0204 ///*KAction *playact =*/ new KAction(i18n("P&lay"), QString ("player_play"), KShortcut (), this, SLOT(play ()), actionCollection (), "play"); 0205 ///*KAction *pauseact =*/ new KAction(i18n("&Pause"), QString ("player_pause"), KShortcut (), this, SLOT(pause ()), actionCollection (), "pause"); 0206 ///*KAction *stopact =*/ new KAction(i18n("&Stop"), QString ("player_stop"), KShortcut (), this, SLOT(stop ()), actionCollection (), "stop"); 0207 //new KAction (i18n ("Increase Volume"), QString ("player_volume"), KShortcut (), this, SLOT (increaseVolume ()), actionCollection (), "edit_volume_up"); 0208 //new KAction (i18n ("Decrease Volume"), QString ("player_volume"), KShortcut (), this, SLOT (decreaseVolume ()), actionCollection (), "edit_volume_down"); 0209 Source *source = m_sources ["urlsource"]; 0210 KMPlayer::ControlPanel * panel = m_view->controlPanel (); 0211 QVariantList::const_iterator it = args.begin (); 0212 QVariantList::const_iterator end = args.end (); 0213 int turned_off_features = 0; 0214 for ( ; it != end; ++it) { 0215 QString arg = (*it).toString(); 0216 int equalPos = arg.indexOf("="); 0217 if (equalPos > 0) { 0218 QString name = arg.left(equalPos).toLower(); 0219 QString value = arg.right(arg.size() - equalPos - 1); 0220 if (value.at(0)=='\"') 0221 value = value.right (value.size () - 1); 0222 if (value.at (value.size () - 1) == '\"') 0223 value.truncate (value.size () - 1); 0224 qCDebug(LOG_KMPLAYER_PART) << "name=" << name << " value=" << value; 0225 if (name == "href") { 0226 m_href_url = value; 0227 } else if (name == QString::fromLatin1("target")) { 0228 m_target = value; 0229 } else if (name == QString::fromLatin1("width")) { 0230 m_noresize = true; 0231 m_expected_view_width = value.toInt (); 0232 } else if (name == QString::fromLatin1("height")) { 0233 m_noresize = true; 0234 m_expected_view_height = value.toInt (); 0235 } else if (name == QString::fromLatin1("controls")) { 0236 //http://service.real.com/help/library/guides/production8/realpgd.htm?src=noref,rnhmpg_080301,rnhmtn,nosrc 0237 //http://service.real.com/help/library/guides/production8/htmfiles/control.htm 0238 QStringList sl = value.split(QChar (',')); 0239 const QStringList::const_iterator e = sl.constEnd (); 0240 for (QStringList::const_iterator i = sl.constBegin (); i != e; ++i) { 0241 QString val_lower ((*i).toLower ()); 0242 if (val_lower == QString::fromLatin1("imagewindow")) { 0243 SET_FEAT_ON (Feat_ImageWindow | Feat_Viewer) 0244 } else if (val_lower == QString::fromLatin1("all")) { 0245 m_features = (Feat_Controls | Feat_StatusBar); 0246 } else if (val_lower == QString::fromLatin1("tacctrl")) { 0247 SET_FEAT_ON (Feat_Label) 0248 } else if (val_lower == QString::fromLatin1("controlpanel")) { 0249 SET_FEAT_ON (Feat_Controls) 0250 } else if (val_lower == QString::fromLatin1("infovolumepanel")){ 0251 SET_FEAT_ON (Feat_Controls) // TODO 0252 } else if (val_lower == QString::fromLatin1("positionfield") || 0253 val_lower == QString::fromLatin1("positionslider")) { 0254 setAutoControls (false); 0255 panel->positionSlider ()->show (); 0256 SET_FEAT_ON (Feat_Controls) 0257 } else if ( val_lower == QString::fromLatin1("homectrl")) { 0258 setAutoControls (false); 0259 panel->button (KMPlayer::ControlPanel::button_config)->show(); 0260 } else if (val_lower == QString::fromLatin1("mutectrl") || 0261 val_lower == QString::fromLatin1("mutevolume")) { 0262 setAutoControls (false); 0263 panel->volumeBar()->setMinimumSize (QSize (20, panel->volumeBar()->minimumSize ().height ())); 0264 panel->volumeBar()->show (); 0265 SET_FEAT_ON (Feat_Controls) 0266 } else if (val_lower == QString::fromLatin1("rwctrl")) { 0267 setAutoControls (false); 0268 panel->button (KMPlayer::ControlPanel::button_back)->show (); // rewind ? 0269 SET_FEAT_ON (Feat_Controls) 0270 } else if ( val_lower == QString::fromLatin1("ffctrl")) { 0271 setAutoControls (false); 0272 panel->button(KMPlayer::ControlPanel::button_forward)->show(); 0273 m_features = Feat_Controls; 0274 } else if ( val_lower ==QString::fromLatin1("stopbutton")) { 0275 setAutoControls (false); 0276 panel->button (KMPlayer::ControlPanel::button_stop)->show (); 0277 SET_FEAT_ON (Feat_Controls) 0278 } else if (val_lower == QString::fromLatin1("playbutton") || 0279 val_lower ==QString::fromLatin1("playonlybutton")) { 0280 setAutoControls (false); 0281 panel->button (KMPlayer::ControlPanel::button_play)->show (); 0282 SET_FEAT_ON (Feat_Controls) 0283 } else if (val_lower ==QString::fromLatin1("pausebutton")) { 0284 setAutoControls (false); 0285 panel->button (KMPlayer::ControlPanel::button_pause)->show (); 0286 SET_FEAT_ON (Feat_Controls) 0287 } else if (val_lower == QString::fromLatin1("statusbar") || 0288 val_lower == QString::fromLatin1("statusfield")) { 0289 SET_FEAT_ON (Feat_StatusBar) 0290 } else if (val_lower == QString::fromLatin1("infopanel")) { 0291 SET_FEAT_ON (Feat_InfoPanel) 0292 } else if (val_lower == QString::fromLatin1("playlist")) { 0293 SET_FEAT_ON (Feat_PlayList) 0294 } else if (val_lower==QString::fromLatin1("volumeslider")) { 0295 SET_FEAT_ON (Feat_VolumeSlider) 0296 setAutoControls (false); 0297 panel->volumeBar()->show (); 0298 panel->volumeBar()->setMinimumSize (QSize (20, panel->volumeBar()->minimumSize ().height ())); 0299 } 0300 } 0301 } else if (name == QString::fromLatin1("uimode")) { 0302 QString val_lower (value.toLower ()); 0303 if (val_lower == QString::fromLatin1("full")) 0304 SET_FEAT_ON (Feat_All & ~(Feat_PlayList | Feat_ImageWindow)) 0305 // TODO: invisible, none, mini 0306 } else if (name == QString::fromLatin1("nolabels")) { 0307 SET_FEAT_OFF (Feat_Label) 0308 } else if (name == QString::fromLatin1("nocontrols")) { 0309 SET_FEAT_OFF (Feat_Controls | Feat_VolumeSlider) 0310 } else if (name == QString::fromLatin1("showdisplay")) { 0311 // the author name, the clip name, and the copyright information 0312 if (getBoolValue (value)) 0313 SET_FEAT_ON (Feat_InfoPanel) 0314 else 0315 SET_FEAT_OFF (Feat_InfoPanel) 0316 } else if (name == QString::fromLatin1("showcontrols") || 0317 name == QString::fromLatin1("controller")) { 0318 if (getBoolValue (value)) 0319 SET_FEAT_ON (Feat_Viewer | Feat_Controls) 0320 else 0321 SET_FEAT_OFF (Feat_Controls | Feat_VolumeSlider) 0322 } else if (name == QString::fromLatin1("showstatusbar")) { 0323 if (getBoolValue (value)) 0324 SET_FEAT_ON (Feat_Viewer | Feat_StatusBar) 0325 else 0326 SET_FEAT_OFF (Feat_StatusBar) 0327 // else showcaptioning/showgotobar/showpositioncontrols/showtracker 0328 } else if (name == QString::fromLatin1("console")) { 0329 m_group = value.isEmpty() ? QString::fromLatin1("_anonymous") : value; 0330 } else if (name == QString::fromLatin1("__khtml__pluginbaseurl")) { 0331 m_docbase = QUrl (value); 0332 } else if (name == QString::fromLatin1("src")) { 0333 m_src_url = value; 0334 } else if (name == QString::fromLatin1("filename")) { 0335 m_file_name = value; 0336 } else if (name == QString::fromLatin1 ("fullscreenmode")) { 0337 show_fullscreen = getBoolValue (value); 0338 } else if (name == QString::fromLatin1 ("autostart")) { 0339 source->setAutoPlay (getBoolValue (value)); 0340 } 0341 // volume/clicktoplay/transparentatstart/animationatstart 0342 // autorewind/displaysize/border 0343 if (!name.startsWith (QString::fromLatin1 ("__khtml__"))) 0344 convertNode <KMPlayer::Element> (source->document ())->setAttribute (name, value); 0345 } 0346 } 0347 if (turned_off_features) { 0348 if (m_features == Feat_Unknown) 0349 m_features = (Feat_All & ~(Feat_PlayList | Feat_ImageWindow | Feat_StatusBar)); 0350 m_features &= ~turned_off_features; 0351 } 0352 //KParts::Part::setWidget (m_view); 0353 setXMLFile("kmplayerpartui.rc"); 0354 /*connect (panel->zoom50Action, SIGNAL (triggered (bool)), 0355 this, SLOT (setMenuZoom (bool))); 0356 panel->zoomMenu ()->connectItem (KMPlayer::ControlPanel::menu_zoom100, 0357 this, SLOT (setMenuZoom (int))); 0358 panel->zoomMenu ()->connectItem (KMPlayer::ControlPanel::menu_zoom150, 0359 this, SLOT (setMenuZoom (int)));*/ 0360 0361 m_view->setNoInfoMessages (m_features != Feat_InfoPanel); 0362 if (m_features == Feat_InfoPanel) { 0363 m_view->initDock (m_view->infoPanel ()); 0364 } else if (m_features == Feat_PlayList) { 0365 m_view->initDock (m_view->playList ()); 0366 } else if (m_features == Feat_StatusBar) { 0367 m_view->initDock (m_view->statusBar ()); 0368 } else { 0369 m_view->initDock (m_view->viewArea ()); 0370 if (m_features & Feat_StatusBar) { 0371 m_view->setStatusBarMode (KMPlayer::View::SB_Show); 0372 m_expected_view_height -= m_view->statusBar ()->height (); 0373 } 0374 if (m_features & (Feat_Controls | Feat_VolumeSlider)) { 0375 m_view->setControlPanelMode (m_features & Feat_Viewer ? KMPlayer::View::CP_Show : KMPlayer::View::CP_Only); 0376 m_expected_view_height -= m_view->controlPanel ()->height (); 0377 } else if (parent ()) 0378 m_view->setControlPanelMode (KMPlayer::View::CP_Hide); 0379 else 0380 m_view->setControlPanelMode (KMPlayer::View::CP_AutoHide); 0381 } 0382 bool group_member = !m_group.isEmpty () && m_group != QString::fromLatin1("_unique") && m_features != Feat_Unknown; 0383 if (!group_member || m_features & Feat_Viewer) { 0384 // not part of a group or we're the viewer 0385 connectPanel (m_view->controlPanel ()); 0386 if (m_features & Feat_StatusBar) { 0387 last_time_left = 0; 0388 connect (this, &KMPlayer::PartBase::positioned, 0389 this, &KMPlayerPart::statusPosition); 0390 m_playtime_info = new QLabel("--:--"); 0391 m_view->statusBar()->addPermanentWidget(m_playtime_info); 0392 } 0393 } 0394 if (group_member) { 0395 KMPlayerPartList::iterator i =kmplayerpart_static->partlist.begin (); 0396 KMPlayerPartList::iterator e =kmplayerpart_static->partlist.end (); 0397 GroupPredicate pred (this, m_group); 0398 for (i = std::find_if (i, e, pred); 0399 i != e; 0400 i = std::find_if (++i, e, pred)) { 0401 // found viewer and control part, exchange players now 0402 KMPlayerPart * vp = (m_features & Feat_Viewer) ? this : *i; 0403 KMPlayerPart * cp = (m_features & Feat_Viewer) ? *i : this; 0404 cp->connectToPart (vp); 0405 } 0406 } else 0407 m_group.truncate (0); 0408 kmplayerpart_static->partlist.push_back (this); 0409 0410 if (m_view->isFullScreen () != show_fullscreen) 0411 m_view->fullScreen (); 0412 } 0413 0414 #undef SET_FEAT_ON 0415 #undef SET_FEAT_OFF 0416 0417 KMPlayerPart::~KMPlayerPart () { 0418 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerPart::~KMPlayerPart"; 0419 //if (!m_group.isEmpty ()) { 0420 KMPlayerPartList::iterator i = std::find (kmplayerpart_static->partlist.begin (), kmplayerpart_static->partlist.end (), this); 0421 if (i != kmplayerpart_static->partlist.end ()) 0422 kmplayerpart_static->partlist.erase (i); 0423 else 0424 qCCritical(LOG_KMPLAYER_PART) << "KMPlayerPart::~KMPlayerPart group lost" << endl; 0425 //} 0426 if (!m_grab_file.isEmpty ()) 0427 ::unlink (m_grab_file.toLocal8Bit ().data ()); 0428 if (m_source) 0429 m_source->deactivate (); 0430 m_config = nullptr; 0431 kmplayerpart_static->unref (); 0432 } 0433 0434 void KMPlayerPart::processCreated (KMPlayer::Process *p) { 0435 #ifdef KMPLAYER_WITH_NPP 0436 if (KMPlayer::NpPlayer* nppProcess = qobject_cast<KMPlayer::NpPlayer*>(p)) { 0437 if (m_wait_npp_loaded) 0438 connect (nppProcess, &KMPlayer::NpPlayer::loaded, this, &KMPlayerPart::nppLoaded); 0439 connect (nppProcess, &KMPlayer::NpPlayer::evaluateRequested, 0440 m_liveconnectextension, &KMPlayerLiveConnectExtension::handleEvaluateRequest); 0441 connect (m_liveconnectextension, &KMPlayerLiveConnectExtension::requestGet, 0442 nppProcess, &KMPlayer::NpPlayer::requestGet); 0443 connect (m_liveconnectextension, &KMPlayerLiveConnectExtension::requestCall, 0444 nppProcess, &KMPlayer::NpPlayer::requestCall); 0445 } 0446 #endif 0447 } 0448 0449 bool KMPlayerPart::allowRedir (const QUrl & url) const 0450 { 0451 return KUrlAuthorized::authorizeUrlAction ("redirect", m_docbase, url); 0452 } 0453 0454 void KMPlayerPart::setAutoControls (bool b) { 0455 m_auto_controls = b; 0456 m_view->controlPanel ()->setAutoControls (b); 0457 } 0458 0459 void KMPlayerPart::viewerPartDestroyed (QObject * o) { 0460 if (o == m_master) 0461 m_master = nullptr; 0462 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerPart(" << this << ")::viewerPartDestroyed"; 0463 const KMPlayerPartList::iterator e =kmplayerpart_static->partlist.end(); 0464 KMPlayerPartList::iterator i = std::find_if (kmplayerpart_static->partlist.begin (), e, GroupPredicate (this, m_group)); 0465 if (i != e && *i != this) 0466 (*i)->updatePlayerMenu (m_view->controlPanel ()); 0467 } 0468 0469 void KMPlayerPart::viewerPartProcessChanged (const char *) { 0470 const KMPlayerPartList::iterator e =kmplayerpart_static->partlist.end(); 0471 KMPlayerPartList::iterator i = std::find_if (kmplayerpart_static->partlist.begin (), e, GroupPredicate (this, m_group)); 0472 if (i != e && *i != this) 0473 (*i)->updatePlayerMenu (m_view->controlPanel ()); 0474 } 0475 0476 void KMPlayerPart::viewerPartSourceChanged(Source *o, Source *s) { 0477 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerPart::source changed " << m_master; 0478 if (m_master && m_view) { 0479 connectSource (o, s); 0480 m_master->updatePlayerMenu (m_view->controlPanel ()); 0481 } 0482 } 0483 0484 bool KMPlayerPart::openUrl(const QUrl& _url) { 0485 QUrl url; 0486 KParts::OpenUrlArguments args = arguments (); 0487 Source * urlsource = m_sources ["urlsource"]; 0488 KMPlayerPartList::iterator i =kmplayerpart_static->partlist.begin (); 0489 KMPlayerPartList::iterator e =kmplayerpart_static->partlist.end (); 0490 GroupPredicate pred (this, m_group); 0491 bool emit_started = !m_settings->clicktoplay; 0492 0493 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerPart::openUrl " << _url.url() << " " << args.mimeType();; 0494 if (args.mimeType () == "application/x-shockwave-flash" || 0495 args.mimeType () == "application/futuresplash") { 0496 m_wait_npp_loaded = true; 0497 urlsource->setAvoidRedirects (true); 0498 } 0499 0500 if (m_wait_npp_loaded && (_url.isEmpty () || _url == m_docbase)) { 0501 url = QUrl ("about:empty"); 0502 m_wait_npp_loaded = emit_started = false; 0503 } else if (!m_file_name.isEmpty () && (_url.isEmpty () || _url == m_docbase)) { 0504 url = m_docbase.resolved(QUrl(m_file_name)); // fix misdetected SRC attr 0505 } else if (_url != m_docbase) { 0506 url = _url; 0507 if (!m_file_name.isEmpty() && _url.url().indexOf(m_file_name) < 0) { 0508 QUrl u = QUrl::fromUserInput(m_file_name); 0509 if ((u.scheme () == QLatin1String("mms")) || 0510 _url.scheme().isEmpty()) { 0511 // see if we somehow have to merge these 0512 int p = _url.port (); 0513 if (p > 0) 0514 u.setPort (p); 0515 if (u.path ().isEmpty ()) 0516 u.setPath (QChar ('/') + _url.host ()); 0517 if (allowRedir (u)) { 0518 url = u; 0519 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerPart::openUrl compose " << m_file_name << " " << _url.url() << " ->" << u.url(); 0520 } 0521 } 0522 } 0523 } else { // if url is the container document, then it's an empty URL 0524 if (m_features & Feat_Viewer) // damn, look in the group 0525 for (i = std::find_if (i, e, pred); 0526 i != e; 0527 i = std::find_if (++i, e, pred)) 0528 if (!(*i)->url ().isEmpty ()) { 0529 url = (*i)->url (); 0530 break; 0531 } 0532 } 0533 if (!m_href_url.isEmpty () && 0534 !KUrlAuthorized::authorizeUrlAction ( 0535 "redirect", url, m_docbase.resolved(QUrl(m_href_url)))) 0536 m_href_url.truncate (0); 0537 if (m_href_url.isEmpty ()) 0538 setUrl (url.url ()); 0539 0540 if (url.isEmpty ()) { 0541 if (!m_master && !(m_features & Feat_Viewer)) 0542 // no master set, wait for a viewer to attach or timeout 0543 QTimer::singleShot (50, this, &KMPlayerPart::waitForImageWindowTimeOut); 0544 return true; 0545 } 0546 m_src_url = url.url (); 0547 0548 if (!m_group.isEmpty () && !(m_features & Feat_Viewer)) { 0549 // group member, not the image window 0550 for (i = std::find_if (i, e, pred); 0551 i != e; 0552 i = std::find_if (++i, e, pred)) 0553 if ((*i)->url ().isEmpty ()) // image window created w/o url 0554 return (*i)->startUrl (_url); 0555 QTimer::singleShot (50, this, &KMPlayerPart::waitForImageWindowTimeOut); 0556 //qCCritical(LOG_KMPLAYER_PART) << "Not the ImageWindow and no ImageWindow found" << endl; 0557 return true; 0558 } 0559 if (!m_view || !url.isValid ()) 0560 return false; 0561 0562 if (!args.mimeType ().isEmpty ()) 0563 urlsource->document ()->mrl ()->mimetype = args.mimeType (); 0564 0565 startUrl (url); 0566 0567 if (emit_started && urlsource->autoPlay ()) { 0568 Q_EMIT started (nullptr); 0569 m_started_emited = true; 0570 } 0571 return true; 0572 } 0573 0574 void 0575 KMPlayerPart::openUrl(const QUrl& u, const QString& t, const QString& srv) { 0576 m_browserextension->requestOpenURL (u, t, srv); 0577 } 0578 0579 bool KMPlayerPart::openNewURL (const QUrl & url) { 0580 m_file_name.truncate (0); 0581 m_href_url.truncate (0); 0582 m_sources ["urlsource"]->setAutoPlay (true); 0583 return openUrl (url); 0584 } 0585 0586 bool KMPlayerPart::startUrl(const QUrl &uri, const QString &img) 0587 { 0588 Source * src = sources () ["urlsource"]; 0589 QUrl url (uri); 0590 qCDebug(LOG_KMPLAYER_PART) << "uri '" << uri << "' img '" << img; 0591 if (url.isEmpty ()) { 0592 url = QUrl::fromUserInput(m_src_url); 0593 } else if (m_settings->grabhref && !m_href_url.isEmpty ()) { 0594 static int counter; 0595 m_href_url = m_docbase.resolved(QUrl(m_href_url)).url (); 0596 m_grab_file = QString ("%1grab-%2-%3.jpg") 0597 .arg (QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+ "kmplayer/") 0598 .arg (getpid ()) 0599 .arg (counter++); 0600 Node *n = new GrabDocument (this, url.url (), m_grab_file, src); 0601 src->setUrl (url.url ()); 0602 m_src_url = m_href_url; 0603 src->setDocument (n, n); 0604 setSource (src); 0605 if (m_source->avoidRedirects ()) 0606 m_source->activate(); 0607 return true; 0608 } 0609 if ((m_settings->clicktoplay || !m_href_url.isEmpty ()) && 0610 (m_features & Feat_Viewer || 0611 Feat_Unknown == m_features) && 0612 m_expected_view_width > 10 && 0613 m_expected_view_height > 10 && 0614 parent () && 0615 !strcmp ("KHTMLPart", parent ()->metaObject ()->className())) { 0616 QString pic (img); 0617 if (!pic.isEmpty ()) { 0618 QFile file (pic); 0619 if (!file.exists ()) { 0620 m_grab_file.truncate (0); 0621 pic.truncate (0); 0622 } else if (!file.size ()) { 0623 pic.truncate (0); 0624 } 0625 } 0626 QString img = pic.isEmpty () 0627 ? QUrl::fromLocalFile (KIconLoader::global()->iconPath ( 0628 QString::fromLatin1 ("video-x-generic"), 0629 #ifdef KMPLAYER_WITH_CAIRO 0630 -128 0631 #else 0632 -32 0633 #endif 0634 )).url () 0635 : pic; 0636 #ifdef KMPLAYER_WITH_CAIRO 0637 QString smil = QString::fromLatin1 ( 0638 "<smil><head><layout>" 0639 "<region id='reg1' left='12.5%' top='5%' right='12.5%' bottom='5%' " 0640 "background-color='#202030' showBackground='whenActive'/>" 0641 "<region id='reg2'/>" 0642 "<region id='reg3'/>" 0643 "</layout>" 0644 "<transition id='clockwipe1' dur='1' type='clockWipe'/>" 0645 "</head>" 0646 "<body>" 0647 "<a href='%1'%2>" 0648 "<img id='image1' src='%3' region='reg%4' fit='meet' " 0649 "begin='.5' dur='indefinite' transIn='clockwipe1'/>" 0650 "</a>" 0651 "<video id='video1' region='reg2' fit='meet'/>" 0652 "</body></smil>" 0653 ).arg (m_target.isEmpty () 0654 ? QString ("#video1") 0655 : m_href_url.isEmpty () ? m_src_url : m_href_url) 0656 .arg (m_target.isEmpty () 0657 ? QString () 0658 : QString (" target='%1'").arg (m_target)) 0659 .arg (img) 0660 .arg (pic.isEmpty () ? "1" : "3"); 0661 QByteArray ba = smil.toUtf8 (); 0662 QTextStream ts (&ba, QIODevice::ReadOnly); 0663 if (m_source) 0664 m_source->deactivate (); 0665 NodePtr doc = src->document (); 0666 KMPlayer::readXML (doc, ts, QString (), false); 0667 NodePtr n = doc->document ()->getElementById ("video1"); 0668 if (n) { 0669 Mrl *mrl = new GenericURL (doc, url.url ()); 0670 n->appendChild (mrl); 0671 mrl->mimetype = doc->document ()->mimetype; 0672 mrl->opener = n; 0673 mrl->setAttributes (convertNode <Element> (doc)->attributes ()); 0674 n->closed (); 0675 NodePtr im = doc->document ()->getElementById ("image1"); 0676 if (im) 0677 im->mrl ()->access_granted = true; 0678 } 0679 doc->document ()->resolved = true; 0680 if (m_source) { 0681 m_source->activate(); 0682 } else { 0683 setSource (src); 0684 if (m_source->avoidRedirects ()) 0685 m_source->activate(); 0686 } 0687 #else 0688 if (m_view->setPicture (img)) { 0689 connect (m_view, &KMPlayer::View::pictureClicked, 0690 this, &KMPlayerPart::pictureClicked); 0691 Q_EMIT completed (); 0692 m_started_emited = false; 0693 } else { 0694 return PartBase::openUrl(m_href_url.isEmpty() ? url : QUrl::fromUserInput(m_href_url)); 0695 } 0696 #endif 0697 return true; 0698 } else 0699 return PartBase::openUrl(m_href_url.isEmpty() ? url : QUrl::fromUserInput(m_href_url)); 0700 } 0701 0702 #ifndef KMPLAYER_WITH_CAIRO 0703 void KMPlayerPart::pictureClicked () { 0704 m_view->setPicture (QString ()); 0705 PartBase::openUrl (QUrl::fromUserInput(m_src_url)); 0706 } 0707 #endif 0708 0709 void KMPlayerPart::waitForImageWindowTimeOut () { 0710 if (!m_master) { 0711 // still no ImageWindow attached, eg. audio only 0712 const KMPlayerPartList::iterator e =kmplayerpart_static->partlist.end(); 0713 GroupPredicate pred (this, m_group); 0714 KMPlayerPartList::iterator i = std::find_if (kmplayerpart_static->partlist.begin (), e, pred); 0715 bool noattach = (i == e || *i == this); 0716 if (noattach) { 0717 if (!url ().isEmpty ()) { 0718 m_features |= KMPlayerPart::Feat_Viewer; //hack, become the view 0719 for (i = std::find_if (kmplayerpart_static->partlist.begin (), e, pred); i != e; i = std::find_if (++i, e, pred)) 0720 (*i)->connectToPart (this); 0721 PartBase::openUrl (url ()); 0722 } else { // see if we can attach to something out there .. 0723 i = std::find_if (kmplayerpart_static->partlist.begin (), e, GroupPredicate (this, m_group, true)); 0724 noattach = (i == e); 0725 } 0726 } 0727 if (!noattach) 0728 connectToPart (*i); 0729 } 0730 } 0731 0732 bool KMPlayerPart::closeUrl () { 0733 if (!m_group.isEmpty ()) { 0734 kmplayerpart_static->partlist.remove (this); 0735 m_group.truncate (0); 0736 } 0737 return PartBase::closeUrl (); 0738 } 0739 0740 void KMPlayerPart::connectToPart (KMPlayerPart * m) { 0741 m_master = m; 0742 m->connectPanel (m_view->controlPanel ()); 0743 m->updatePlayerMenu (m_view->controlPanel ()); 0744 if (m_features & Feat_PlayList) 0745 m->connectPlaylist (m_view->playList ()); 0746 if (m_features & Feat_InfoPanel) 0747 m->connectInfoPanel (m_view->infoPanel ()); 0748 connectSource (m_source, m->source ()); 0749 connect (m, &QObject::destroyed, 0750 this, &KMPlayerPart::viewerPartDestroyed); 0751 connect (m, &KMPlayer::PartBase::processChanged, 0752 this, &KMPlayerPart::viewerPartProcessChanged); 0753 connect (m, &KMPlayer::PartBase::sourceChanged, 0754 this, &KMPlayerPart::viewerPartSourceChanged); 0755 if (m_features & Feat_StatusBar) { 0756 last_time_left = 0; 0757 connect (m, &KMPlayer::PartBase::positioned, 0758 this, &KMPlayerPart::statusPosition); 0759 m_playtime_info = new QLabel("--:--"); 0760 m_view->statusBar()->addPermanentWidget(m_playtime_info); 0761 } 0762 } 0763 0764 void KMPlayerPart::setLoaded (int percentage) { 0765 PartBase::setLoaded (percentage); 0766 if (percentage < 100) { 0767 m_browserextension->setLoadingProgress (percentage); 0768 m_browserextension->infoMessage 0769 // xgettext: no-c-format 0770 (QString::number (percentage) + i18n ("% Cache fill")); 0771 } 0772 } 0773 0774 void KMPlayerPart::playingStarted () { 0775 const KMPlayerPartList::iterator e =kmplayerpart_static->partlist.end(); 0776 KMPlayerPartList::iterator i = std::find_if (kmplayerpart_static->partlist.begin (), e, GroupPredicate (this, m_group)); 0777 if (i != e && *i != this && m_view && (*i)->source()) { 0778 m_view->controlPanel ()->setPlaying (true); 0779 m_view->controlPanel ()->showPositionSlider(!!(*i)->source()->length ()); 0780 m_view->controlPanel()->enableSeekButtons((*i)->source()->isSeekable()); 0781 Q_EMIT loading (100); 0782 } else if (m_source) 0783 KMPlayer::PartBase::playingStarted (); 0784 else 0785 return; // ugh 0786 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerPart::processStartedPlaying "; 0787 if (m_settings->sizeratio && !m_noresize && m_source->width() > 0 && m_source->height() > 0) 0788 m_liveconnectextension->setSize (m_source->width(), m_source->height()); 0789 m_browserextension->setLoadingProgress (100); 0790 if (m_started_emited && !m_wait_npp_loaded) { 0791 Q_EMIT completed (); 0792 m_started_emited = false; 0793 } 0794 m_liveconnectextension->started (); 0795 m_browserextension->infoMessage (i18n("KMPlayer: Playing")); 0796 } 0797 0798 void KMPlayerPart::playingStopped () { 0799 KMPlayer::PartBase::playingStopped (); 0800 if (m_started_emited && !m_wait_npp_loaded) { 0801 m_started_emited = false; 0802 m_browserextension->setLoadingProgress (100); 0803 Q_EMIT completed (); 0804 } 0805 m_liveconnectextension->finished (); 0806 m_browserextension->infoMessage (i18n ("KMPlayer: Stop Playing")); 0807 if (m_view) 0808 m_view->controlPanel ()->setPlaying (false); 0809 } 0810 0811 void KMPlayerPart::nppLoaded () { 0812 if (m_started_emited && m_wait_npp_loaded) { 0813 m_wait_npp_loaded = false; 0814 m_started_emited = false; 0815 m_browserextension->setLoadingProgress (100); 0816 Q_EMIT completed (); 0817 } 0818 } 0819 0820 void KMPlayerPart::setMenuZoom (int /*id*/) { 0821 /*int w = 0, h = 0; 0822 if (m_source) 0823 m_source->dimensions (w, h); 0824 if (id == KMPlayer::ControlPanel::menu_zoom100) { 0825 m_liveconnectextension->setSize (w, h); 0826 return; 0827 } 0828 float scale = 1.5; 0829 if (id == KMPlayer::ControlPanel::menu_zoom50) 0830 scale = 0.5; 0831 if (m_view) 0832 m_liveconnectextension->setSize (int (scale * m_view->viewArea ()->width ()), 0833 int (scale * m_view->viewArea ()->height()));*/ 0834 } 0835 0836 void KMPlayerPart::statusPosition (int pos, int length) { 0837 int left = (length - pos) / 10; 0838 if (left != last_time_left) { 0839 last_time_left = left; 0840 QString text ("--:--"); 0841 if (left > 0) { 0842 int h = left / 3600; 0843 int m = (left % 3600) / 60; 0844 int s = left % 60; 0845 if (h > 0) 0846 text = QString::asprintf ("%d:%02d:%02d", h, m, s); 0847 else 0848 text = QString::asprintf ("%02d:%02d", m, s); 0849 } 0850 m_playtime_info->setText(text); 0851 } 0852 } 0853 0854 QString KMPlayerPart::doEvaluate (const QString &script) { 0855 return m_liveconnectextension->evaluate ( 0856 QString ("this.__kmplayer__res=" ) + script); 0857 } 0858 0859 //--------------------------------------------------------------------- 0860 0861 KMPlayerBrowserExtension::KMPlayerBrowserExtension (KMPlayerPart * parent) 0862 : KParts::BrowserExtension (parent) { 0863 } 0864 0865 void KMPlayerBrowserExtension::urlChanged (const QString & url) { 0866 Q_EMIT setLocationBarUrl (url); 0867 } 0868 0869 void KMPlayerBrowserExtension::setLoadingProgress (int percentage) { 0870 Q_EMIT loadingProgress (percentage); 0871 } 0872 0873 void KMPlayerBrowserExtension::saveState (QDataStream & stream) { 0874 stream << static_cast <PartBase *> (parent ())->url ().url (); 0875 } 0876 0877 void KMPlayerBrowserExtension::restoreState (QDataStream & stream) { 0878 QString url; 0879 stream >> url; 0880 static_cast <PartBase *> (parent ())->openUrl (QUrl(url)); 0881 } 0882 0883 void KMPlayerBrowserExtension::requestOpenURL (const QUrl & url, const QString & target, const QString & service) 0884 { 0885 KParts::OpenUrlArguments args; 0886 KParts::BrowserArguments bargs; 0887 bargs.frameName = target; 0888 args.setMimeType (service); 0889 Q_EMIT openUrlRequest (url, args, bargs); 0890 } 0891 0892 //--------------------------------------------------------------------- 0893 /* 0894 * add 0895 * .error.errorCount 0896 * .error.item(count) 0897 * .errorDescription 0898 * .errorCode 0899 * .controls.stop() 0900 * .controls.play() 0901 */ 0902 0903 enum JSCommand { 0904 notsupported, 0905 canpause, canplay, canstop, canseek, 0906 isfullscreen, isloop, isaspect, showcontrolpanel, 0907 length, width, height, playstate, position, source, setsource, protocol, 0908 gotourl, nextentry, jsc_pause, play, preventry, start, stop, 0909 volume, setvolume, 0910 prop_error, prop_source, prop_volume, 0911 prop_qt_status, prop_qt_rate 0912 }; 0913 0914 struct JSCommandEntry 0915 { 0916 const char * name; 0917 JSCommand command; 0918 const char * defaultvalue; 0919 const KParts::LiveConnectExtension::Type rettype; 0920 }; 0921 0922 // keep this list in alphabetic order 0923 // http://service.real.com/help/library/guides/realonescripting/browse/htmfiles/embedmet.htm 0924 static const JSCommandEntry JSCommandList [] = { 0925 { "CanPause", canpause, nullptr, KParts::LiveConnectExtension::TypeBool }, 0926 { "CanPlay", canplay, nullptr, KParts::LiveConnectExtension::TypeBool }, 0927 { "CanStop", canstop, nullptr, KParts::LiveConnectExtension::TypeBool }, 0928 { "DoGotoURL", notsupported, nullptr, KParts::LiveConnectExtension::TypeVoid }, 0929 { "DoNextEntry", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0930 { "DoPause", jsc_pause, "true", KParts::LiveConnectExtension::TypeBool }, 0931 { "DoPlay", play, nullptr, KParts::LiveConnectExtension::TypeBool }, 0932 { "DoPlayPause", play, nullptr, KParts::LiveConnectExtension::TypeBool }, 0933 { "DoPrevEntry", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0934 { "DoStop", stop, nullptr, KParts::LiveConnectExtension::TypeBool }, 0935 { "FileName", prop_source, nullptr, KParts::LiveConnectExtension::TypeString }, 0936 { "GetAuthor", notsupported, "noname", KParts::LiveConnectExtension::TypeString }, 0937 { "GetAutoGoToURL", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 0938 { "GetBackgroundColor", notsupported, "#ffffff", KParts::LiveConnectExtension::TypeString }, 0939 { "GetBandwidthAverage", notsupported, "64", KParts::LiveConnectExtension::TypeNumber }, 0940 { "GetBandwidthCurrent", notsupported, "64", KParts::LiveConnectExtension::TypeNumber }, 0941 { "GetBufferingTimeElapsed", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0942 { "GetBufferingTimeRemaining", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0943 { "GetCanSeek", canseek, nullptr, KParts::LiveConnectExtension::TypeBool }, 0944 { "GetCenter", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 0945 { "GetClipHeight", height, nullptr, KParts::LiveConnectExtension::TypeNumber }, 0946 { "GetClipWidth", width, nullptr, KParts::LiveConnectExtension::TypeNumber }, 0947 { "GetConnectionBandwidth", notsupported, "64", KParts::LiveConnectExtension::TypeNumber }, 0948 { "GetConsole", notsupported, "unknown", KParts::LiveConnectExtension::TypeString }, 0949 { "GetConsoleEvents", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0950 { "GetControls", notsupported, "buttons", KParts::LiveConnectExtension::TypeString }, 0951 { "GetCopyright", notsupported, "(c) whoever", KParts::LiveConnectExtension::TypeString }, 0952 { "GetCurrentEntry", notsupported, "1", KParts::LiveConnectExtension::TypeNumber }, 0953 { "GetDuration", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0954 { "GetDRMInfo", notsupported, "RNBA", KParts::LiveConnectExtension::TypeString }, 0955 { "GetDoubleSize", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0956 { "GetEntryAbstract", notsupported, "abstract", KParts::LiveConnectExtension::TypeString }, 0957 { "GetEntryAuthor", notsupported, "noname", KParts::LiveConnectExtension::TypeString }, 0958 { "GetEntryCopyright", notsupported, "(c)", KParts::LiveConnectExtension::TypeString }, 0959 { "GetEntryTitle", notsupported, "title", KParts::LiveConnectExtension::TypeString }, 0960 { "GetFullScreen", isfullscreen, nullptr, KParts::LiveConnectExtension::TypeBool }, 0961 { "GetImageStatus", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0962 { "GetLastErrorMoreInfoURL", notsupported, "no error", KParts::LiveConnectExtension::TypeString }, 0963 { "GetLastErrorRMACode", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0964 { "GetLastErrorSeverity", notsupported, "6", KParts::LiveConnectExtension::TypeNumber }, 0965 { "GetLastErrorUserCode", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0966 { "GetLastErrorUserString", notsupported, "no error", KParts::LiveConnectExtension::TypeString }, 0967 { "GetLastMessage", notsupported, "no error", KParts::LiveConnectExtension::TypeString }, 0968 { "GetLastStatus", notsupported, "no error", KParts::LiveConnectExtension::TypeString }, 0969 { "GetLength", length, nullptr, KParts::LiveConnectExtension::TypeNumber }, 0970 { "GetLiveState", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0971 { "GetLoop", isloop, nullptr, KParts::LiveConnectExtension::TypeBool }, 0972 { "GetMaintainAspect", isaspect, nullptr, KParts::LiveConnectExtension::TypeBool }, 0973 { "GetMute", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0974 { "GetNumEntries", notsupported, "1", KParts::LiveConnectExtension::TypeNumber }, 0975 { "GetNumLoop", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0976 { "GetNumSources", notsupported, "1", KParts::LiveConnectExtension::TypeNumber }, 0977 { "GetOriginalSize", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 0978 { "GetPacketsEarly", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0979 { "GetPacketsLate", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0980 { "GetPacketsMissing", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0981 { "GetPacketsOutOfOrder", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0982 { "GetPacketsReceived", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0983 { "GetPacketsTotal", notsupported, "0", KParts::LiveConnectExtension::TypeNumber }, 0984 { "GetPlayState", playstate, nullptr, KParts::LiveConnectExtension::TypeNumber }, 0985 { "GetPluginStatus", prop_qt_status, nullptr, KParts::LiveConnectExtension::TypeString }, 0986 { "GetPosition", position, nullptr, KParts::LiveConnectExtension::TypeNumber }, 0987 { "GetPreFetch", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0988 { "GetRate", prop_qt_rate, nullptr, KParts::LiveConnectExtension::TypeNumber }, 0989 { "GetShowAbout", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0990 { "GetShowPreferences", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0991 { "GetShowStatistics", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0992 { "GetShuffle", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 0993 { "GetSource", source, nullptr, KParts::LiveConnectExtension::TypeString }, 0994 { "GetSourceTransport", protocol, nullptr, KParts::LiveConnectExtension::TypeString }, 0995 { "GetStereoState", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 0996 { "GetTitle", notsupported, "title", KParts::LiveConnectExtension::TypeString }, 0997 { "GetVersionInfo", notsupported, "version", KParts::LiveConnectExtension::TypeString }, 0998 { "GetVolume", volume, "100", KParts::LiveConnectExtension::TypeNumber }, 0999 { "GetWantErrors", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 1000 { "GetWantKeyboardEvents", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 1001 { "GetWantMouseEvents", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 1002 { "HasNextEntry", notsupported, "false", KParts::LiveConnectExtension::TypeBool }, 1003 { "Pause", jsc_pause, nullptr, KParts::LiveConnectExtension::TypeBool }, 1004 { "Play", play, nullptr, KParts::LiveConnectExtension::TypeBool }, 1005 { "SetAuthor", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1006 { "SetAutoGoToURL", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1007 { "SetAutoStart", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1008 { "SetBackgroundColor", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1009 { "SetCanSeek", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1010 { "SetCenter", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1011 { "SetConsole", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1012 { "SetConsoleEvents", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1013 { "SetControls", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1014 { "SetCopyright", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1015 { "SetCurrentPosition", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1016 { "SetDoubleSize", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1017 { "SetFileName", setsource, nullptr, KParts::LiveConnectExtension::TypeBool }, 1018 { "SetFullScreen", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1019 { "SetImageStatus", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1020 { "SetLoop", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1021 { "SetMaintainAspect", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1022 { "SetMute", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1023 { "SetNumLoop", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1024 { "SetOriginalSize", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1025 { "SetPosition", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1026 { "SetPreFetch", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1027 { "SetShowAbout", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1028 { "SetShowPreferences", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1029 { "SetShowStatistics", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1030 { "SetShuffle", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1031 { "SetSource", setsource, nullptr, KParts::LiveConnectExtension::TypeBool }, 1032 { "SetTitle", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1033 { "SetVolume", setvolume, "true", KParts::LiveConnectExtension::TypeBool }, 1034 { "SetWantErrors", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1035 { "SetWantKeyboardEvents", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1036 { "SetWantMouseEvents", notsupported, "true", KParts::LiveConnectExtension::TypeBool }, 1037 { "ShowControls", showcontrolpanel, "true", KParts::LiveConnectExtension::TypeBool }, 1038 { "Start", start, nullptr, KParts::LiveConnectExtension::TypeBool }, 1039 { "Stop", stop, nullptr, KParts::LiveConnectExtension::TypeBool }, 1040 { "Volume", prop_volume, "100", KParts::LiveConnectExtension::TypeNumber }, 1041 { "errorCode", prop_error, "0",KParts::LiveConnectExtension::TypeNumber }, 1042 { "pause", jsc_pause, nullptr, KParts::LiveConnectExtension::TypeBool }, 1043 { "play", play, nullptr, KParts::LiveConnectExtension::TypeBool }, 1044 { "put", prop_source, nullptr, KParts::LiveConnectExtension::TypeString }, 1045 { "stop", stop, nullptr, KParts::LiveConnectExtension::TypeBool }, 1046 { "volume", volume, nullptr, KParts::LiveConnectExtension::TypeBool }, 1047 }; 1048 1049 static const JSCommandEntry * getJSCommandEntry (const char * name, int start = 0, int end = sizeof (JSCommandList)/sizeof (JSCommandEntry)) { 1050 if (end - start < 2) { 1051 if (start != end && !strcasecmp (JSCommandList[start].name, name)) 1052 return &JSCommandList[start]; 1053 return nullptr; 1054 } 1055 int mid = (start + end) / 2; 1056 int cmp = strcasecmp (JSCommandList[mid].name, name); 1057 if (cmp < 0) 1058 return getJSCommandEntry (name, mid + 1, end); 1059 if (cmp > 0) 1060 return getJSCommandEntry (name, start, mid); 1061 return &JSCommandList[mid]; 1062 } 1063 1064 KMPlayerLiveConnectExtension::KMPlayerLiveConnectExtension (KMPlayerPart * parent) 1065 : KParts::LiveConnectExtension (parent), player (parent), 1066 lastJSCommandEntry (nullptr), 1067 object_counter (0), 1068 m_started (false), 1069 m_enablefinish (false), 1070 m_evaluating (false), 1071 m_skip_put (false) { 1072 connect (parent, &KParts::ReadOnlyPart::started, this, &KMPlayerLiveConnectExtension::started); 1073 } 1074 1075 KMPlayerLiveConnectExtension::~KMPlayerLiveConnectExtension() { 1076 qCDebug(LOG_KMPLAYER_PART) << "KMPlayerLiveConnectExtension::~KMPlayerLiveConnectExtension()"; 1077 } 1078 1079 void KMPlayerLiveConnectExtension::started () { 1080 m_started = true; 1081 } 1082 1083 void KMPlayerLiveConnectExtension::finished () { 1084 if (m_started && m_enablefinish) { 1085 KParts::LiveConnectExtension::ArgList args; 1086 args.push_back (qMakePair (KParts::LiveConnectExtension::TypeString, QString("if (window.onFinished) onFinished();"))); 1087 Q_EMIT partEvent (0, "eval", args); 1088 m_started = true; 1089 m_enablefinish = false; 1090 } 1091 } 1092 1093 QString KMPlayerLiveConnectExtension::evaluate (const QString &script) { 1094 KParts::LiveConnectExtension::ArgList args; 1095 args.push_back(qMakePair(KParts::LiveConnectExtension::TypeString, script)); 1096 script_result.clear (); 1097 Q_EMIT partEvent (0, "eval", args); 1098 //qCDebug(LOG_KMPLAYER_PART) << script << script_result; 1099 return script_result; 1100 } 1101 1102 void KMPlayerLiveConnectExtension::handleEvaluateRequest ( 1103 const QString & scr, bool store, QString & result) { 1104 m_evaluating = true; 1105 1106 QString script (scr); 1107 script = script.replace ('\\', "\\\\"); 1108 script = script.replace ('\n', "\\n"); 1109 script = script.replace ('\r', ""); 1110 script = script.replace ('"', "\\\""); 1111 QString obj_var = QString ("this.__kmplayer__obj_%1").arg (object_counter); 1112 script = obj_var + QString ("=eval(\"%1\")").arg (script); 1113 QString eval_result = evaluate (script); 1114 1115 bool clear_result = true; 1116 if (!store) { 1117 result = eval_result; 1118 if (scr.startsWith ("this.__kmplayer__obj_")) { 1119 // TODO add dbus method for this 1120 int p = scr.indexOf ("=null", 21); 1121 if (p > -1) { 1122 int i = scr.mid (21, p - 21).toInt (); 1123 if (i == (int)object_counter-1) 1124 object_counter--; // works most of the time :-) 1125 } 1126 } 1127 } else { 1128 script = QString ("this.__kmplayer__res=typeof(%1)").arg (obj_var); 1129 QString result_type = evaluate (script); 1130 1131 if (result_type == "string") { 1132 result = QString ("s:") + eval_result; 1133 } else if (result_type == "object" || 1134 result_type == "function" || 1135 result_type.startsWith ("[")) { 1136 result = QString ("o:") + obj_var; 1137 clear_result = false; 1138 object_counter++; 1139 } else if (result_type == "number") { 1140 result = QString ("n:") + eval_result; 1141 } else if (result_type == "boolean") { 1142 result = QString ("b:") + eval_result; 1143 } else if (result_type == "undefined" || result_type == "null") { 1144 result = QString ("u:") + eval_result; 1145 } else { 1146 result = "error"; 1147 } 1148 } 1149 if (clear_result) 1150 evaluate (obj_var + "=null"); 1151 1152 script_result.clear (); 1153 1154 m_evaluating = false; 1155 } 1156 1157 static 1158 bool str2LC (const QString s, KParts::LiveConnectExtension::Type &type, QString &rval) { 1159 if (s == "error") 1160 return false; 1161 if (s == "o:function") { 1162 type = KParts::LiveConnectExtension::TypeFunction; 1163 } else if (s.startsWith (QChar ('\'')) && s.endsWith (QChar ('\''))) { 1164 type = KParts::LiveConnectExtension::TypeString; 1165 rval = s.mid (1, s.size () - 2); 1166 } else if (s == "true" || s == "false") { 1167 type = KParts::LiveConnectExtension::TypeBool; 1168 rval = s; 1169 } else { 1170 bool ok; 1171 s.toInt (&ok); 1172 if (!ok) 1173 s.toDouble (&ok); 1174 if (ok) { 1175 type = KParts::LiveConnectExtension::TypeNumber; 1176 rval = s; 1177 } else { 1178 type = KParts::LiveConnectExtension::TypeVoid; 1179 rval = s; 1180 } 1181 } 1182 return true; 1183 } 1184 1185 bool KMPlayerLiveConnectExtension::get 1186 (const unsigned long id, const QString & name, 1187 KParts::LiveConnectExtension::Type & type, 1188 unsigned long & rid, QString & rval) 1189 { 1190 if (name.startsWith ("__kmplayer__obj_")) { 1191 if (m_evaluating) 1192 return false; 1193 rid = 0; 1194 type = KParts::LiveConnectExtension::TypeString; 1195 rval = "Access denied"; 1196 return true; 1197 } 1198 if (name.startsWith ("__kmplayer_func")) { 1199 rid = id; 1200 type = KParts::LiveConnectExtension::TypeFunction; 1201 return true; 1202 } 1203 if (name.startsWith ("__kmplayer_util_") || 1204 redir_funcs.indexOf(name) >= 0) 1205 return false; 1206 if (name == "__kmplayer_unique_name") { 1207 rval = QString ("__kmplayer__obj_%1").arg (object_counter); 1208 type = KParts::LiveConnectExtension::TypeString; 1209 rid = id; 1210 object_counter++; 1211 m_allow = rval; 1212 return true; 1213 } 1214 rid = id; 1215 QString req_result; 1216 Q_EMIT requestGet (id, name, &req_result); 1217 if (!req_result.isEmpty ()) { 1218 if (str2LC (req_result, type, rval)) { 1219 if (KParts::LiveConnectExtension::TypeFunction == type) { 1220 m_skip_put = true; 1221 if (!redir_funcs.size ()) 1222 evaluate ( 1223 "this.__kmplayer_util_make_arg = function(arg) {" 1224 " var t = typeof arg;" 1225 " if (t == 'number')" 1226 " return 'n:' + arg;" 1227 " if (t == 'object') {" 1228 " var s = this.__kmplayer_unique_name;" 1229 " this[s] = arg;" 1230 " return 'o:this.' + s;" 1231 " }" 1232 " if (t == 'function') {" 1233 " var s = this.__kmplayer_unique_name;" 1234 " this[s] = arg;" 1235 " return 'o:this.' + s;" 1236 " }" 1237 " if (t == 'boolean')" 1238 " return 'b:' + arg;" 1239 " if (t == 'undefined' || t == null)" 1240 " return 'u:' + arg;" 1241 " var s = '' + arg;" 1242 " s = s.replace('\\\\', '\\\\\\\\');" 1243 " s = s.replace('\\n', '\\\\n');" 1244 " return 's:' + s;" 1245 "}"); 1246 evaluate (QString ( 1247 "this.%1=function(){" 1248 " var args=[];" 1249 " for (var i=0;i<arguments.length;++i)" 1250 " args.push (this.__kmplayer_util_make_arg(" 1251 " arguments[i]));" 1252 " return this.__kmplayer_func('%2',args.join('\\n'));" 1253 "}") 1254 .arg (name) 1255 .arg (name)); 1256 redir_funcs.push_back (name); 1257 m_skip_put = false; 1258 return false; 1259 } 1260 return true; 1261 } 1262 } 1263 qCDebug(LOG_KMPLAYER_PART) << "[01;35mget[00m " << name; 1264 const JSCommandEntry * entry = getJSCommandEntry (name.toLatin1 ().constData ()); 1265 if (!entry) 1266 return false; 1267 type = entry->rettype; 1268 switch (entry->command) { 1269 case prop_source: 1270 type = KParts::LiveConnectExtension::TypeString; 1271 rval = player->url ().url (); 1272 break; 1273 case prop_volume: 1274 if (player->view ()) 1275 rval = QString::number (player->viewWidget ()->controlPanel()->volumeBar()->value()); 1276 break; 1277 case prop_error: 1278 type = KParts::LiveConnectExtension::TypeNumber; 1279 rval = QString::number (0); 1280 break; 1281 case prop_qt_status: 1282 rval = player->getStatus (); 1283 break; 1284 case prop_qt_rate: 1285 rval = QString::number (0.0); 1286 if (player->source() && player->source()->document() && 1287 player->source()->document()->state != 1288 KMPlayer::Node::state_deferred && 1289 player->source()->document()->unfinished ()) 1290 rval = QString::number (1.0); 1291 break; 1292 default: 1293 lastJSCommandEntry = entry; 1294 type = KParts::LiveConnectExtension::TypeFunction; 1295 } 1296 return true; 1297 } 1298 1299 bool KMPlayerLiveConnectExtension::put 1300 (const unsigned long, const QString & name, const QString & val) { 1301 if (m_skip_put) 1302 return false; 1303 if (name == "__kmplayer__res") { 1304 script_result = val; 1305 return true; 1306 } 1307 if (name.startsWith ("__kmplayer__obj_")) { 1308 script_result = val; 1309 if (name == m_allow) { 1310 m_allow.clear (); 1311 return false; 1312 } 1313 return !m_evaluating; 1314 } 1315 1316 qCDebug(LOG_KMPLAYER_PART) << "[01;35mput[00m " << name << "=" << val; 1317 1318 const JSCommandEntry * entry = getJSCommandEntry (name.toLatin1 ().constData ()); 1319 if (!entry) 1320 return false; 1321 switch (entry->command) { 1322 case prop_source: { 1323 const QUrl url = QUrl::fromUserInput(val); 1324 if (player->allowRedir (url)) 1325 player->openNewURL (url); 1326 break; 1327 } 1328 case prop_volume: 1329 if (player->view ()) 1330 player->viewWidget ()->controlPanel()->volumeBar()->setValue(val.toInt ()); 1331 break; 1332 default: 1333 return false; 1334 } 1335 return true; 1336 } 1337 1338 static QString unescapeArg (const QString &arg) { 1339 QString s; 1340 bool last_escape = false; 1341 for (int i = 0; i < arg.length (); ++i) 1342 switch (arg[i].unicode ()) { 1343 case '\\': 1344 if (last_escape) { 1345 s += QChar ('\\'); 1346 last_escape = false; 1347 } else { 1348 last_escape = true; 1349 } 1350 break; 1351 case 'n': 1352 if (last_escape) { 1353 s += QChar ('\n'); 1354 last_escape = false; 1355 break; 1356 } // else fall through 1357 default: 1358 if (last_escape) { 1359 qCCritical(LOG_KMPLAYER_PART) << "unescape error " << arg; 1360 last_escape = false; 1361 } 1362 s += arg[i]; 1363 } 1364 return s; 1365 } 1366 1367 bool KMPlayerLiveConnectExtension::call 1368 (const unsigned long id, const QString & name, 1369 const QStringList & args, KParts::LiveConnectExtension::Type & type, 1370 unsigned long & rid, QString & rval) { 1371 QString func = name; 1372 QString req_result; 1373 QStringList arglst; 1374 int oid = id; 1375 QList<QString>::const_iterator it = args.begin (); 1376 if (func == "__kmplayer_func") { 1377 if ( it != args.end ()) { 1378 func = *it; 1379 oid = 0; 1380 if ( ++it != args.end ()) { 1381 QStringList a = (*it).split ("\n"); 1382 for (QStringList::iterator i = a.begin(); i != a.end (); ++i) 1383 arglst << ((*i).startsWith ("s:") ? unescapeArg (*i) : *i); 1384 } 1385 } else { 1386 return false; 1387 } 1388 } else { 1389 for (; it != args.end (); ++it) { 1390 bool ok; 1391 int iv = (*it).toInt (&ok); 1392 if (ok) { 1393 arglst << QString ("n:%1").arg (iv); 1394 } else { 1395 double dv = (*it).toDouble (&ok); 1396 if (ok) { 1397 arglst << QString ("n:%1").arg (dv); 1398 } else { 1399 arglst << QString ("s:%1").arg (*it); 1400 } 1401 } 1402 } 1403 } 1404 rid = oid; 1405 Q_EMIT requestCall (oid, func, arglst, &req_result); 1406 if (!req_result.isEmpty ()) { 1407 if (str2LC (req_result, type, rval)) 1408 return true; 1409 } 1410 qCDebug(LOG_KMPLAYER_PART) << "[01;35mentry[00m " << func; 1411 const JSCommandEntry * entry = lastJSCommandEntry; 1412 const QByteArray latin1 = func.toLatin1 (); 1413 if (!entry || strcmp (entry->name, latin1.constData ())) 1414 entry = getJSCommandEntry (latin1.constData ()); 1415 if (!entry) 1416 return false; 1417 for (QStringList::size_type i = 0; i < args.size (); ++i) 1418 qCDebug(LOG_KMPLAYER_PART) << " " << args[i]; 1419 if (!player->view ()) 1420 return false; 1421 type = entry->rettype; 1422 switch (entry->command) { 1423 case notsupported: 1424 if (entry->rettype != KParts::LiveConnectExtension::TypeVoid) 1425 rval = entry->defaultvalue; 1426 break; 1427 case canpause: 1428 rval = (player->playing () && !player->viewWidget ()->controlPanel()->button (KMPlayer::ControlPanel::button_pause)->isChecked ()) ? "true" : "false"; 1429 break; 1430 case canplay: 1431 rval = (!player->playing () || player->viewWidget ()->controlPanel()->button (KMPlayer::ControlPanel::button_pause)->isChecked ()) ? "true" : "false"; 1432 break; 1433 case canstop: 1434 rval = player->playing () ? "true" : "false"; 1435 break; 1436 case canseek: 1437 rval = player->source ()->isSeekable () ? "true" : "false"; 1438 break; 1439 case play: 1440 if (args.size ()) { 1441 const QUrl url = QUrl::fromUserInput(args.first ()); 1442 if (player->allowRedir (url)) 1443 player->openNewURL (url); 1444 } else 1445 player->play (); 1446 rval = "true"; 1447 break; 1448 case start: 1449 player->play (); 1450 rval = "true"; 1451 break; 1452 case stop: 1453 player->stop (); 1454 rval = "true"; 1455 break; 1456 case showcontrolpanel: 1457 if (args.size () && 1458 (args.first () == QString::fromLatin1 ("0") || 1459 args.first () == QString::fromLatin1 ("false"))) 1460 player->viewWidget ()->setControlPanelMode (KMPlayer::View::CP_Hide); 1461 else 1462 player->viewWidget ()->setControlPanelMode (KMPlayer::View::CP_Show); 1463 break; 1464 case jsc_pause: 1465 player->pause (); 1466 rval = "true"; 1467 break; 1468 case isloop: 1469 rval = player->settings ()->loop ? "true" : "false"; 1470 break; 1471 case isaspect: 1472 rval = player->settings ()->sizeratio ? "true" : "false"; 1473 break; 1474 case isfullscreen: 1475 rval = player->viewWidget ()->isFullScreen () ? "true" : "false"; 1476 break; 1477 case length: 1478 rval.setNum (player->source ()->length ()); 1479 break; 1480 case width: 1481 rval.setNum (player->source ()->width ()); 1482 break; 1483 case height: 1484 rval.setNum (player->source ()->height ()); 1485 break; 1486 case playstate: // FIXME 0-6 1487 rval = player->playing () ? "3" : "0"; 1488 break; 1489 case position: 1490 rval.setNum (player->position ()); 1491 break; 1492 case protocol: 1493 rval = player->url ().scheme(); 1494 break; 1495 case setsource: 1496 rval ="false"; 1497 if (args.size ()) { 1498 const QUrl url = QUrl::fromUserInput (args.first ()); 1499 if (player->allowRedir (url) && player->openNewURL (url)) 1500 rval = "true"; 1501 } 1502 break; 1503 case setvolume: 1504 if (!args.size ()) 1505 return false; 1506 player->viewWidget ()->controlPanel()->volumeBar()->setValue(args.first ().toInt ()); 1507 rval = "true"; 1508 break; 1509 case source: 1510 rval = player->url ().url (); 1511 break; 1512 case volume: 1513 if (player->view ()) 1514 rval = QString::number (player->viewWidget ()->controlPanel()->volumeBar()->value()); 1515 break; 1516 default: 1517 return false; 1518 } 1519 return true; 1520 } 1521 1522 void KMPlayerLiveConnectExtension::unregister (const unsigned long) { 1523 } 1524 1525 void KMPlayerLiveConnectExtension::setSize (int w, int h) { 1526 KMPlayer::View * view = static_cast <KMPlayer::View*> (player->view ()); 1527 if (view->controlPanelMode () == KMPlayer::View::CP_Show) 1528 h += view->controlPanel()->height(); 1529 const QString jscode = QString::asprintf("try { eval(\"this.setAttribute('WIDTH',%d);this.setAttribute('HEIGHT',%d)\"); } catch(e){}", w, h); 1530 KParts::LiveConnectExtension::ArgList args; 1531 args.push_back (qMakePair (KParts::LiveConnectExtension::TypeString, jscode)); 1532 Q_EMIT partEvent (0, "eval", args); 1533 } 1534 1535 #include "moc_kmplayer_part.cpp"