File indexing completed on 2024-04-14 15:00:58

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