1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 #include <math.h>
21 #include "config-kmplayer.h"
22 #include <unistd.h>
23 #include <qstring.h>
24 #include <qfile.h>
25 #include <qfileinfo.h>
26 #include <qtimer.h>
27 #include <qlayout.h>
28 #include <qtablewidget.h>
29 #include <qlineedit.h>
30 #include <qslider.h>
31 #include <qcombobox.h>
32 #include <qcheckbox.h>
33 #include <qspinbox.h>
34 #include <qlabel.h>
35 #include <qfontmetrics.h>
36 #include <qwhatsthis.h>
37 #include <QList>
38 #include <QtDBus/QtDBus>
39 #include <QtCore/QDir>
40 #include <QtCore/QUrl>
41 #include <QHeaderView>
42 #include <QNetworkCookie>
43 
44 #include <kdebug.h>
45 #include <kprotocolmanager.h>
46 #include <kfiledialog.h>
47 #include <kmessagebox.h>
48 #include <klocale.h>
49 #include <kstandarddirs.h>
50 #include <kshell.h>
51 #include <kio/job.h>
52 #include <kio/accessmanager.h>
53 
54 #include "kmplayer_def.h"
55 #include "kmplayerconfig.h"
56 #include "kmplayerview.h"
57 #include "kmplayercontrolpanel.h"
58 #include "kmplayerprocess.h"
59 #include "kmplayerpartbase.h"
60 #include "masteradaptor.h"
61 #include "streammasteradaptor.h"
62 #ifdef KMPLAYER_WITH_NPP
63 # include "callbackadaptor.h"
64 # include "streamadaptor.h"
65 #endif
66 
67 using namespace KMPlayer;
68 
ProcessInfo(const char * nm,const QString & lbl,const char ** supported,MediaManager * mgr,PreferencesPage * prefs)69 ProcessInfo::ProcessInfo (const char *nm, const QString &lbl,
70         const char **supported, MediaManager* mgr, PreferencesPage *prefs)
71  : name (nm),
72    label (lbl),
73    supported_sources (supported),
74    manager (mgr),
75    config_page (prefs) {
76     if (config_page)
77         manager->player ()->settings ()->addPage (config_page);
78 }
79 
~ProcessInfo()80 ProcessInfo::~ProcessInfo () {
81     delete config_page;
82 }
83 
supports(const char * source) const84 bool ProcessInfo::supports (const char *source) const {
85     for (const char ** s = supported_sources; s[0]; ++s) {
86         if (!strcmp (s[0], source))
87             return true;
88     }
89     return false;
90 }
91 
92 //------------------------%<----------------------------------------------------
93 
getPath(const KUrl & url)94 static QString getPath (const KUrl & url) {
95     QString p = QUrl::fromPercentEncoding (url.url ().toAscii ());
96     if (p.startsWith (QString ("file:/"))) {
97         int i = 0;
98         p = p.mid (5);
99         for (; i < p.size () && p[i] == QChar ('/'); ++i)
100             ;
101         //kDebug () << "getPath " << p.mid (i-1);
102         if (i > 0)
103             return p.mid (i-1);
104         return QString (QChar ('/') + p);
105     }
106     return p;
107 }
108 
encodeFileOrUrl(const KUrl & url)109 static QString encodeFileOrUrl (const KUrl &url)
110 {
111     return url.isEmpty ()
112         ? QString ()
113         : QString::fromLocal8Bit (QFile::encodeName (
114                     url.isLocalFile ()
115                     ? url.toLocalFile ()
116                     : QUrl::fromPercentEncoding (url.url ().toLocal8Bit ())));
117 }
118 
encodeFileOrUrl(const QString & str)119 static QString encodeFileOrUrl (const QString &str)
120 {
121     if (!str.startsWith (QString ("dvd:")) &&
122             !str.startsWith (QString ("vcd:")) &&
123             !str.startsWith (QString ("tv:")) &&
124             !str.startsWith (QString ("cdda:")))
125         return encodeFileOrUrl (KUrl (str));
126     return str;
127 }
128 
setupProcess(QProcess ** process)129 static void setupProcess (QProcess **process)
130 {
131     delete *process;
132     *process = new QProcess;
133     QStringList env = (*process)->systemEnvironment ();
134     const QStringList::iterator e = env.end ();
135     for (QStringList::iterator i = env.begin (); i != e; ++i)
136         if ((*i).startsWith ("SESSION_MANAGER")) {
137             env.erase (i);
138             break;
139         }
140     (*process)->setEnvironment (env);
141 }
142 
killProcess(QProcess * process,QWidget * widget)143 static void killProcess (QProcess *process, QWidget *widget) {
144     if (!process || !process->pid ())
145         return;
146     process->terminate ();
147     if (!process->waitForFinished (1000)) {
148         process->kill ();
149         if (!process->waitForFinished (1000) && widget)
150             KMessageBox::error (widget,
151                     i18n ("Failed to end player process."), i18n ("Error"));
152     }
153 }
154 
outputToView(View * view,const QByteArray & ba)155 static void outputToView (View *view, const QByteArray &ba)
156 {
157     if (view && ba.size ())
158         view->addText (QString::fromLocal8Bit (ba.constData ()));
159 }
160 
Process(QObject * parent,ProcessInfo * pinfo,Settings * settings)161 Process::Process (QObject *parent, ProcessInfo *pinfo, Settings *settings)
162  : QObject (parent),
163    IProcess (pinfo),
164    m_source (0L),
165    m_settings (settings),
166    m_old_state (IProcess::NotRunning),
167    m_process (0L),
168    m_job(0L),
169    m_process_state (QProcess::NotRunning)
170 {}
171 
~Process()172 Process::~Process () {
173     quit ();
174     delete m_process;
175     if (user)
176         user->processDestroyed (this);
177 }
178 
init()179 void Process::init () {
180 }
181 
initProcess()182 void Process::initProcess () {
183     setupProcess (&m_process);
184     m_process_state = QProcess::NotRunning;
185     connect (m_process, SIGNAL (stateChanged (QProcess::ProcessState)),
186             this, SLOT (processStateChanged (QProcess::ProcessState)));
187     if (m_source) m_source->setPosition (0);
188 }
189 
widget()190 WId Process::widget () {
191     return view () && user && user->viewer ()
192         ? user->viewer ()->windowHandle ()
193         : 0;
194 }
195 
mrl() const196 Mrl *Process::mrl () const {
197     if (user)
198         return user->getMrl ();
199     return NULL;
200 }
201 
processRunning(QProcess * process)202 static bool processRunning (QProcess *process) {
203     return process && process->state () > QProcess::NotRunning;
204 }
205 
running() const206 bool Process::running () const {
207     return processRunning (m_process);
208 }
209 
setAudioLang(int)210 void Process::setAudioLang (int) {}
211 
setSubtitle(int)212 void Process::setSubtitle (int) {}
213 
pause()214 void Process::pause () {
215 }
216 
unpause()217 void Process::unpause () {
218 }
219 
seek(int,bool)220 bool Process::seek (int /*pos*/, bool /*absolute*/) {
221     return false;
222 }
223 
volume(int,bool)224 void Process::volume (int /*pos*/, bool /*absolute*/) {
225 }
226 
saturation(int,bool)227 bool Process::saturation (int /*pos*/, bool /*absolute*/) {
228     return false;
229 }
230 
hue(int,bool)231 bool Process::hue (int /*pos*/, bool /*absolute*/) {
232     return false;
233 }
234 
contrast(int,bool)235 bool Process::contrast (int /*pos*/, bool /*absolute*/) {
236     return false;
237 }
238 
brightness(int,bool)239 bool Process::brightness (int /*pos*/, bool /*absolute*/) {
240     return false;
241 }
242 
grabPicture(const QString &,int)243 bool Process::grabPicture (const QString &/*file*/, int /*pos*/) {
244     m_old_state = m_state = Buffering;
245     setState (Ready);
246     return false;
247 }
248 
stop()249 void Process::stop () {
250 }
251 
quit()252 void Process::quit () {
253     killProcess (m_process, view ());
254     setState (IProcess::NotRunning);
255 }
256 
setState(IProcess::State newstate)257 void Process::setState (IProcess::State newstate) {
258     if (m_state != newstate) {
259         bool need_timer = m_old_state == m_state;
260         m_old_state = m_state;
261         m_state = newstate;
262         if (need_timer)
263             QTimer::singleShot (0, this, SLOT (rescheduledStateChanged ()));
264     }
265 }
266 
rescheduledStateChanged()267 KDE_NO_EXPORT void Process::rescheduledStateChanged () {
268     IProcess::State old_state = m_old_state;
269     m_old_state = m_state;
270     if (user) {
271         user->stateChange (this, old_state, m_state);
272     } else {
273         if (m_state > IProcess::Ready)
274             kError() << "Process running, mrl disappeared" << endl;
275         delete this;
276     }
277 }
278 
play()279 bool Process::play () {
280     Mrl *m = mrl ();
281     if (!m)
282         return false;
283     bool nonstdurl = m->src.startsWith ("tv:/") ||
284         m->src.startsWith ("dvd:") ||
285         m->src.startsWith ("cdda:") ||
286         m->src.startsWith ("vcd:");
287     QString url = nonstdurl ? m->src : m->absolutePath ();
288     bool changed = m_url != url;
289     m_url = url;
290     if (user) // FIXME: remove check
291         user->starting (this);
292     if (!changed ||
293             KUrl (m_url).isLocalFile () ||
294             nonstdurl ||
295             (m_source && m_source->avoidRedirects ()))
296         return deMediafiedPlay ();
297     m_job = KIO::stat (m_url, KIO::HideProgressInfo);
298     connect (m_job, SIGNAL (result (KJob *)), this, SLOT (result (KJob *)));
299     return true;
300 }
301 
deMediafiedPlay()302 bool Process::deMediafiedPlay () {
303     return false;
304 }
305 
result(KJob * job)306 void Process::result (KJob * job) {
307     KIO::UDSEntry entry = static_cast <KIO::StatJob *> (job)->statResult ();
308     QString url = entry.stringValue (KIO::UDSEntry::UDS_LOCAL_PATH);
309     if (!url.isEmpty ())
310         m_url = url;
311     m_job = 0L;
312     deMediafiedPlay ();
313 }
314 
terminateJobs()315 void Process::terminateJobs () {
316     if (m_job) {
317         m_job->kill ();
318         m_job = 0L;
319     }
320 }
321 
ready()322 bool Process::ready () {
323     setState (IProcess::Ready);
324     return true;
325 }
326 
processStateChanged(QProcess::ProcessState nstate)327 void Process::processStateChanged (QProcess::ProcessState nstate)
328 {
329     if (QProcess::Starting == m_process_state) {
330         if (QProcess::NotRunning == nstate)
331             setState (IProcess::NotRunning);
332         else if (state () == IProcess::Ready)
333             setState (IProcess::Buffering);
334         m_process_state = nstate;
335     }
336 }
337 
startProcess(const QString & program,const QStringList & args)338 void Process::startProcess (const QString &program, const QStringList &args)
339 {
340     m_process_state = QProcess::Starting;
341     m_process->start (program, args);
342 }
343 
view() const344 View *Process::view () const {
345     return m_source ? m_source->player ()->viewWidget () : NULL;
346 }
347 
348 //-----------------------------------------------------------------------------
349 
RecordDocument(const QString & url,const QString & rurl,const QString & rec,Source * src)350 RecordDocument::RecordDocument (const QString &url, const QString &rurl,
351         const QString &rec, Source *src)
352  : SourceDocument (src, url),
353    record_file (rurl),
354    recorder (rec) {
355     id = id_node_record_document;
356 }
357 
begin()358 void RecordDocument::begin () {
359     if (!media_info) {
360         media_info = new MediaInfo (this, MediaManager::AudioVideo);
361         media_info->create ();
362     }
363     media_info->media->play ();
364 }
365 
message(MessageType msg,void * content)366 void RecordDocument::message (MessageType msg, void *content) {
367     switch (msg) {
368     case MsgMediaFinished:
369         deactivate ();
370         break;
371     default:
372         SourceDocument::message (msg, content);
373     }
374 }
375 
deactivate()376 void RecordDocument::deactivate () {
377     state = state_deactivated;
378     ((MediaManager *) role (RoleMediaManager))->player ()->recorderStopped ();
379     Document::deactivate ();
380 }
381 
recordDocument(ProcessUser * user)382 static RecordDocument *recordDocument (ProcessUser *user) {
383     Mrl *mrl = user ? user->getMrl () : NULL;
384     return mrl && id_node_record_document == mrl->id
385         ? static_cast <RecordDocument *> (mrl) : NULL;
386 }
387 
388 //-----------------------------------------------------------------------------
389 
proxyForURL(const KUrl & url,QString & proxy)390 static bool proxyForURL (const KUrl &url, QString &proxy) {
391     KProtocolManager::slaveProtocol (url, proxy);
392     return !proxy.isNull ();
393 }
394 
395 //-----------------------------------------------------------------------------
396 
MPlayerBase(QObject * parent,ProcessInfo * pinfo,Settings * settings)397 KDE_NO_CDTOR_EXPORT MPlayerBase::MPlayerBase (QObject *parent, ProcessInfo *pinfo, Settings * settings)
398     : Process (parent, pinfo, settings),
399       m_needs_restarted (false) {
400     m_process = new QProcess;
401 }
402 
~MPlayerBase()403 KDE_NO_CDTOR_EXPORT MPlayerBase::~MPlayerBase () {
404 }
405 
initProcess()406 KDE_NO_EXPORT void MPlayerBase::initProcess () {
407     Process::initProcess ();
408     const KUrl &url (m_source->url ());
409     if (!url.isEmpty ()) {
410         QString proxy_url;
411         if (KProtocolManager::useProxy () && proxyForURL (url, proxy_url)) {
412             QStringList env = m_process->environment ();
413             env << (QString ("http_proxy=") + proxy_url);
414             m_process->setEnvironment (env);
415         }
416     }
417     connect (m_process, SIGNAL (bytesWritten (qint64)),
418             this, SLOT (dataWritten (qint64)));
419     connect (m_process, SIGNAL (finished (int, QProcess::ExitStatus)),
420             this, SLOT (processStopped (int, QProcess::ExitStatus)));
421 }
422 
removeQueued(const char * cmd)423 bool MPlayerBase::removeQueued (const char *cmd) {
424     for (QList<QByteArray>::iterator i = commands.begin ();
425             i != commands.end ();
426             ++i)
427         if (!strncmp ((*i).data (), cmd, strlen (cmd))) {
428             commands.erase (i);
429             return true;
430         }
431     return false;
432 }
433 
sendCommand(const QString & cmd)434 KDE_NO_EXPORT bool MPlayerBase::sendCommand (const QString & cmd) {
435     if (running ()) {
436         commands.push_front (QString (cmd + '\n').toAscii ());
437         fprintf (stderr, "eval %s", commands.last ().constData ());
438         if (commands.size () < 2)
439             m_process->write (commands.last ());
440         return true;
441     }
442     return false;
443 }
444 
stop()445 KDE_NO_EXPORT void MPlayerBase::stop () {
446     terminateJobs ();
447 }
448 
quit()449 KDE_NO_EXPORT void MPlayerBase::quit () {
450     if (running ()) {
451         kDebug() << "MPlayerBase::quit";
452         stop ();
453         disconnect (m_process, SIGNAL (finished (int, QProcess::ExitStatus)),
454                 this, SLOT (processStopped (int, QProcess::ExitStatus)));
455         m_process->waitForFinished (2000);
456         if (running ())
457             Process::quit ();
458         commands.clear ();
459         m_needs_restarted = false;
460         processStopped ();
461     }
462     Process::quit ();
463 }
464 
dataWritten(qint64)465 KDE_NO_EXPORT void MPlayerBase::dataWritten (qint64) {
466     if (!commands.size ()) return;
467     kDebug() << "eval done " << commands.last ().data ();
468     commands.pop_back ();
469     if (commands.size ())
470         m_process->write (commands.last ());
471 }
472 
processStopped()473 KDE_NO_EXPORT void MPlayerBase::processStopped () {
474     setState (IProcess::Ready);
475 }
476 
processStopped(int,QProcess::ExitStatus)477 KDE_NO_EXPORT void MPlayerBase::processStopped (int, QProcess::ExitStatus) {
478     kDebug() << "process stopped" << endl;
479     commands.clear ();
480     processStopped ();
481 }
482 
483 //-----------------------------------------------------------------------------
484 
485 static const char *mplayer_supports [] = {
486     "dvdsource", "exitsource", "introsource", "pipesource", "tvscanner", "tvsource", "urlsource", "vcdsource", "audiocdsource", 0L
487 };
488 
MPlayerProcessInfo(MediaManager * mgr)489 MPlayerProcessInfo::MPlayerProcessInfo (MediaManager *mgr)
490  : ProcessInfo ("mplayer", i18n ("&MPlayer"), mplayer_supports,
491          mgr, new MPlayerPreferencesPage ()) {}
492 
create(PartBase * part,ProcessUser * usr)493 IProcess *MPlayerProcessInfo::create (PartBase *part, ProcessUser *usr) {
494     MPlayer *m = new MPlayer (part, this, part->settings ());
495     m->setSource (part->source ());
496     m->user = usr;
497     part->processCreated (m);
498     return m;
499 }
500 
501 KDE_NO_CDTOR_EXPORT
MPlayer(QObject * parent,ProcessInfo * pinfo,Settings * settings)502 MPlayer::MPlayer (QObject *parent, ProcessInfo *pinfo, Settings *settings)
503  : MPlayerBase (parent, pinfo, settings),
504    m_widget (0L),
505    m_transition_state (NotRunning),
506    aid (-1), sid (-1)
507 {}
508 
~MPlayer()509 KDE_NO_CDTOR_EXPORT MPlayer::~MPlayer () {
510     if (m_widget && !m_widget->parent ())
511         delete m_widget;
512 }
513 
init()514 KDE_NO_EXPORT void MPlayer::init () {
515 }
516 
ready()517 KDE_NO_EXPORT bool MPlayer::ready () {
518     Process::ready ();
519     if (user && user->viewer ())
520         user->viewer ()->useIndirectWidget (true);
521     return false;
522 }
523 
deMediafiedPlay()524 KDE_NO_EXPORT bool MPlayer::deMediafiedPlay () {
525     if (running ())
526         return sendCommand (QString ("gui_play"));
527 
528     m_transition_state = NotRunning;
529     if (!m_needs_restarted && running ())
530         quit (); // rescheduling of setState will reset state just-in-time
531 
532     initProcess ();
533     connect (m_process, SIGNAL (readyReadStandardOutput ()),
534             this, SLOT (processOutput ()));
535     connect (m_process, SIGNAL (readyReadStandardError ()),
536             this, SLOT (processOutput ()));
537 
538     m_process_output = QString ();
539     m_source->setPosition (0);
540     if (!m_needs_restarted) {
541         if (m_source->identified ()) {
542             aid = m_source->audioLangId ();
543             sid = m_source->subTitleId ();
544         } else {
545             aid = sid = -1;
546         }
547     } else {
548         m_needs_restarted = false;
549     }
550     alanglist = NULL;
551     slanglist = NULL;
552     slanglist_end = NULL;
553     alanglist_end = NULL;
554     m_request_seek = -1;
555     m_tmpURL.truncate (0);
556 
557     QStringList args;
558     //m_view->consoleOutput ()->clear ();
559     MPlayerPreferencesPage *cfg_page = static_cast <MPlayerPreferencesPage *>(process_info->config_page);
560     QString exe = cfg_page->mplayer_path;
561     if (exe.isEmpty ())
562         exe = "mplayer";
563 
564     args << "-wid" << QString::number (widget ());
565     args << "-slave";
566 
567     QString strVideoDriver = QString (m_settings->videodrivers[m_settings->videodriver].driver);
568     if (!strVideoDriver.isEmpty ()) {
569         args << "-vo" << strVideoDriver.toLower();
570         if (view () && view ()->keepSizeRatio () &&
571                 strVideoDriver.toLower() == QString::fromLatin1 ("x11"))
572             args << "-zoom";
573     }
574 
575     QString strAudioDriver = QString (m_settings->audiodrivers[m_settings->audiodriver].driver);
576     if (!strAudioDriver.isEmpty ())
577         args << "-ao" << strAudioDriver.toLower();
578 
579     if (m_settings->framedrop)
580         args << "-framedrop";
581 
582     if (cfg_page->additionalarguments.length () > 0)
583         args << KShell::splitArgs (cfg_page->additionalarguments);
584 
585     // postproc thingies
586     args << KShell::splitArgs (m_source->filterOptions ());
587 
588     if (m_settings->autoadjustcolors) {
589         args << "-contrast" << QString::number (m_settings->contrast);
590         args << "-brightness" <<QString::number(m_settings->brightness);
591         args << "-hue" << QString::number (m_settings->hue);
592         args << "-saturation" <<QString::number(m_settings->saturation);
593     }
594 
595     if (aid > -1)
596         args << "-aid" << QString::number (aid);
597 
598     if (sid > -1)
599         args << "-sid" << QString::number (sid);
600 
601     for (Node *n = mrl (); n; n = n->parentNode ()) {
602         if (n->id != id_node_group_node && n->id != id_node_playlist_item)
603             break;
604         QString plops = static_cast<Element *>(n)->getAttribute ("mplayeropts");
605         if (!plops.isNull ()) {
606             QStringList sl = plops.split (QChar (' '));
607             for (int i = 0; i < sl.size (); ++i)
608                 args << sl[i];
609             break;
610         }
611     }
612 
613     args << KShell::splitArgs (m_source->options ());
614 
615     KUrl url (m_url);
616     if (!url.isEmpty ()) {
617         if (m_source->url ().isLocalFile ())
618             m_process->setWorkingDirectory
619                 (QFileInfo (m_source->url ().path ()).absolutePath ());
620         if (url.isLocalFile ()) {
621             m_url = url.toLocalFile ();
622             if (cfg_page->alwaysbuildindex &&
623                     (m_url.toLower ().endsWith (".avi") ||
624                      m_url.toLower ().endsWith (".divx")))
625                 args << "-idx";
626         } else {
627             int cache = cfg_page->cachesize;
628             if (cache > 3 && !url.url ().startsWith (QString ("dvd")) &&
629                     !url.url ().startsWith (QString ("vcd")) &&
630                     !m_url.startsWith (QString ("tv://")))
631                 args << "-cache" << QString::number (cache);
632             if (m_url.startsWith (QString ("cdda:/")) &&
633                     !m_url.startsWith (QString ("cdda://")))
634                 m_url = QString ("cdda://") + m_url.mid (6);
635         }
636         if (url.protocol () != QString ("stdin"))
637             args << encodeFileOrUrl (m_url);
638     }
639     Mrl *m = mrl ();
640     if (m && m->repeat > 0)
641         args << "-loop" << QString::number (m->repeat);
642     else if (m_settings->loop)
643         args << "-loop" << 0;
644     args << "-identify";
645     const QString surl = encodeFileOrUrl (m_source->subUrl ());
646     if (!surl.isEmpty ())
647         args << "-sub" << surl;
648     qDebug ("mplayer %s\n", args.join (" ").toLocal8Bit ().constData ());
649 
650     startProcess (exe, args);
651 
652     old_volume = view () ? view ()->controlPanel ()->volumeBar ()->value () : 0;
653 
654     return true;
655 }
656 
stop()657 KDE_NO_EXPORT void MPlayer::stop () {
658     terminateJobs ();
659     if (!m_source || !running ())
660         return;
661     sendCommand (QString ("quit"));
662     MPlayerBase::stop ();
663 }
664 
pause()665 KDE_NO_EXPORT void MPlayer::pause () {
666     if (Paused != m_transition_state) {
667         m_transition_state = Paused;
668         if (!removeQueued ("pause"))
669             sendCommand (QString ("pause"));
670     }
671 }
672 
unpause()673 KDE_NO_EXPORT void MPlayer::unpause () {
674     if (m_transition_state == Paused
675             || (Paused == m_state
676                 && m_transition_state != Playing)) {
677         m_transition_state = Playing;
678         if (!removeQueued ("pause"))
679             sendCommand (QString ("pause"));
680     }
681 }
682 
seek(int pos,bool absolute)683 KDE_NO_EXPORT bool MPlayer::seek (int pos, bool absolute) {
684     if (!m_source || !m_source->hasLength () ||
685             (absolute && m_source->position () == pos))
686         return false;
687     if (m_request_seek >= 0 && commands.size () > 1) {
688         QList<QByteArray>::iterator i = commands.begin ();
689         for (++i; i != commands.end (); ++i)
690             if (!strncmp ((*i).data (), "seek", 4)) {
691                 i = commands.erase (i);
692                 m_request_seek = -1;
693                 break;
694             }
695     }
696     if (m_request_seek >= 0) {
697         //m_request_seek = pos;
698         return false;
699     }
700     m_request_seek = pos;
701     QString cmd;
702     cmd.sprintf ("seek %d %d", pos/10, absolute ? 2 : 0);
703     if (!absolute)
704         pos = m_source->position () + pos;
705     m_source->setPosition (pos);
706     return sendCommand (cmd);
707 }
708 
volume(int incdec,bool absolute)709 KDE_NO_EXPORT void MPlayer::volume (int incdec, bool absolute) {
710     if (absolute)
711         incdec -= old_volume;
712     if (incdec == 0)
713         return;
714     old_volume += incdec;
715     sendCommand (QString ("volume ") + QString::number (incdec));
716 }
717 
saturation(int val,bool absolute)718 KDE_NO_EXPORT bool MPlayer::saturation (int val, bool absolute) {
719     QString cmd;
720     cmd.sprintf ("saturation %d %d", val, absolute ? 1 : 0);
721     return sendCommand (cmd);
722 }
723 
hue(int val,bool absolute)724 KDE_NO_EXPORT bool MPlayer::hue (int val, bool absolute) {
725     QString cmd;
726     cmd.sprintf ("hue %d %d", val, absolute ? 1 : 0);
727     return sendCommand (cmd);
728 }
729 
contrast(int val,bool)730 KDE_NO_EXPORT bool MPlayer::contrast (int val, bool /*absolute*/) {
731     QString cmd;
732     cmd.sprintf ("contrast %d 1", val);
733     return sendCommand (cmd);
734 }
735 
brightness(int val,bool)736 KDE_NO_EXPORT bool MPlayer::brightness (int val, bool /*absolute*/) {
737     QString cmd;
738     cmd.sprintf ("brightness %d 1", val);
739     return sendCommand (cmd);
740 }
741 
grabPicture(const QString & file,int pos)742 KDE_NO_EXPORT bool MPlayer::grabPicture (const QString &file, int pos) {
743     Mrl *m = mrl ();
744     if (m_state > Ready || !m || m->src.isEmpty ())
745         return false; //FIXME
746     initProcess ();
747     m_old_state = m_state = Buffering;
748     unlink (file.toAscii ().constData ());
749     QByteArray ba = file.toLocal8Bit ();
750     ba.append ("XXXXXX");
751     if (mkdtemp ((char *) ba.constData ())) {
752         m_grab_dir = QString::fromLocal8Bit (ba.constData ());
753         QString exe ("mplayer");
754         QStringList args;
755         QString jpgopts ("jpeg:outdir=");
756         jpgopts += KShell::quoteArg (m_grab_dir);
757         args << "-vo" << jpgopts;
758         args << "-frames" << "1" << "-nosound" << "-quiet";
759         if (pos > 0)
760             args << "-ss" << QString::number (pos);
761         args << encodeFileOrUrl (m->src);
762         kDebug () << args.join (" ");
763         m_process->start (exe, args);
764         if (m_process->waitForStarted ()) {
765             m_grab_file = file;
766             setState (Playing);
767             return true;
768         } else {
769             rmdir (ba.constData ());
770             m_grab_dir.truncate (0);
771         }
772     } else {
773         kError () << "mkdtemp failure";
774     }
775     setState (Ready);
776     return false;
777 }
778 
processOutput()779 KDE_NO_EXPORT void MPlayer::processOutput () {
780     const QByteArray ba = m_process->readAllStandardOutput ();
781     const char *str = ba.constData ();
782     int slen = ba.size ();
783     if (!mrl () || slen <= 0) return;
784     View *v = view ();
785 
786     bool ok;
787     QRegExp *patterns = static_cast<MPlayerPreferencesPage *>(process_info->config_page)->m_patterns;
788     QRegExp & m_refURLRegExp = patterns[MPlayerPreferencesPage::pat_refurl];
789     QRegExp & m_refRegExp = patterns[MPlayerPreferencesPage::pat_ref];
790     do {
791         int len = strcspn (str, "\r\n");
792         QString out = m_process_output + QString::fromLocal8Bit (str, len);
793         m_process_output = QString ();
794         str += len;
795         slen -= len;
796         if (slen <= 0) {
797             m_process_output = out;
798             break;
799         }
800         bool process_stats = false;
801         if (str[0] == '\r') {
802             if (slen > 1 && str[1] == '\n') {
803                 str++;
804                 slen--;
805             } else
806                 process_stats = true;
807         }
808         str++;
809         slen--;
810 
811         if (process_stats) {
812             QRegExp & m_posRegExp = patterns[MPlayerPreferencesPage::pat_pos];
813             QRegExp & m_cacheRegExp = patterns[MPlayerPreferencesPage::pat_cache];
814             if (m_posRegExp.indexIn (out) > -1) {
815                 if (m_source->hasLength ()) {
816                     int pos = int (10.0 * m_posRegExp.cap (1).toFloat ());
817                     m_source->setPosition (pos);
818                     m_request_seek = -1;
819                 }
820                 if (Playing == m_transition_state) {
821                     m_transition_state = NotRunning;
822                     setState (Playing);
823                 }
824             } else if (m_cacheRegExp.indexIn (out) > -1) {
825                 m_source->setLoading (int (m_cacheRegExp.cap(1).toDouble()));
826             }
827         } else if (out.startsWith ("ID_LENGTH")) {
828             int pos = out.indexOf ('=');
829             if (pos > 0) {
830                 int l = (int) out.mid (pos + 1).toDouble (&ok);
831                 if (ok && l >= 0) {
832                     m_source->setLength (mrl (), 10 * l);
833                 }
834             }
835         } else if (out.startsWith ("ID_PAUSED")) {
836             if (Paused == m_transition_state) {
837                 m_transition_state = NotRunning;
838                 setState (Paused);
839             }
840         } else if (m_refURLRegExp.indexIn(out) > -1) {
841             kDebug () << "Reference mrl " << m_refURLRegExp.cap (1);
842             if (!m_tmpURL.isEmpty () &&
843                     (m_url.endsWith (m_tmpURL) || m_tmpURL.endsWith (m_url)))
844                 m_source->insertURL (mrl (), m_tmpURL);;
845             KUrl tmp (m_refURLRegExp.cap (1));
846             m_tmpURL = tmp.isLocalFile () ? tmp.toLocalFile () : tmp.url ();
847             if (m_source->url () == m_tmpURL ||
848                     m_url.endsWith (m_tmpURL) || m_tmpURL.endsWith (m_url))
849                 m_tmpURL.truncate (0);
850         } else if (m_refRegExp.indexIn (out) > -1) {
851             kDebug () << "Reference File ";
852             m_tmpURL.truncate (0);
853         } else if (out.startsWith ("ID_VIDEO_WIDTH")) {
854             int pos = out.indexOf ('=');
855             if (pos > 0) {
856                 int w = out.mid (pos + 1).toInt ();
857                 m_source->setDimensions (mrl (), w, m_source->height ());
858             }
859         } else if (out.startsWith ("ID_VIDEO_HEIGHT")) {
860             int pos = out.indexOf ('=');
861             if (pos > 0) {
862                 int h = out.mid (pos + 1).toInt ();
863                 m_source->setDimensions (mrl (), m_source->width (), h);
864             }
865         } else if (out.startsWith ("ID_VIDEO_ASPECT")) {
866             int pos = out.indexOf ('=');
867             if (pos > 0) {
868                 bool ok;
869                 QString val = out.mid (pos + 1);
870                 float a = val.toFloat (&ok);
871                 if (!ok) {
872                     val.replace (',', '.');
873                     a = val.toFloat (&ok);
874                 }
875                 if (ok && a > 0.001)
876                     m_source->setAspect (mrl (), a);
877             }
878         } else if (out.startsWith ("ID_AID_")) {
879             int pos = out.indexOf ('_', 7);
880             if (pos > 0) {
881                 int id = out.mid (7, pos - 7).toInt ();
882                 pos = out.indexOf ('=', pos);
883                 if (pos > 0) {
884                     if (!alanglist_end) {
885                         alanglist = new Source::LangInfo (id, out.mid (pos + 1));
886                         alanglist_end = alanglist;
887                     } else {
888                         alanglist_end->next = new Source::LangInfo (id, out.mid(pos+1));
889                         alanglist_end = alanglist_end->next;
890                     }
891                     kDebug () << "lang " << id << " " << alanglist_end->name;
892                 }
893             }
894         } else if (out.startsWith ("ID_SID_")) {
895             int pos = out.indexOf ('_', 7);
896             if (pos > 0) {
897                 int id = out.mid (7, pos - 7).toInt ();
898                 pos = out.indexOf ('=', pos);
899                 if (pos > 0) {
900                     if (!slanglist_end) {
901                         slanglist = new Source::LangInfo (id, out.mid (pos + 1));
902                         slanglist_end = slanglist;
903                     } else {
904                         slanglist_end->next = new Source::LangInfo (id, out.mid(pos+1));
905                         slanglist_end = slanglist_end->next;
906                     }
907                     kDebug () << "sid " << id << " " << slanglist_end->name;
908                 }
909             }
910         } else if (out.startsWith ("ICY Info")) {
911             int p = out.indexOf ("StreamTitle=", 8);
912             if (p > -1) {
913                 p += 12;
914                 int e = out.indexOf (';', p);
915                 if (e > -1)
916                     e -= p;
917                 QString inf = out.mid (p, e);
918                 mrl ()->document ()->message (MsgInfoString, &inf);
919             }
920         } else if (v) {
921             QRegExp & m_startRegExp = patterns[MPlayerPreferencesPage::pat_start];
922             QRegExp & m_sizeRegExp = patterns[MPlayerPreferencesPage::pat_size];
923             v->addText (out, true);
924             if (!m_source->processOutput (out)) {
925                 // int movie_width = m_source->width ();
926                 if (/*movie_width <= 0 &&*/ m_sizeRegExp.indexIn (out) > -1) {
927                     int movie_width = m_sizeRegExp.cap (1).toInt (&ok);
928                     int movie_height = ok ? m_sizeRegExp.cap (2).toInt (&ok) : 0;
929                     if (ok && movie_width > 0 && movie_height > 0) {
930                         m_source->setDimensions(mrl(),movie_width,movie_height);
931                         m_source->setAspect (mrl(), 1.0*movie_width/movie_height);
932                     }
933                 } else if (m_startRegExp.indexIn (out) > -1) {
934                     if (!m_tmpURL.isEmpty () && m_url != m_tmpURL) {
935                         m_source->insertURL (mrl (), m_tmpURL);;
936                         m_tmpURL.truncate (0);
937                     }
938                     m_source->setIdentified ();
939                     m_source->setLanguages (alanglist, slanglist);
940                     m_source->setLoading (100);
941                     setState (IProcess::Playing);
942                     m_source->setPosition (0);
943                 }
944             }
945         }
946     } while (slen > 0);
947 }
948 
processStopped()949 KDE_NO_EXPORT void MPlayer::processStopped () {
950     if (mrl ()) {
951         QString url;
952         if (!m_grab_dir.isEmpty ()) {
953             QDir dir (m_grab_dir);
954             QStringList files = dir.entryList ();
955             bool renamed = false;
956             for (int i = 0; i < files.size (); ++i) {
957                 kDebug() << files[i];
958                 if (files[i] == "." || files[i] == "..")
959                     continue;
960                 if (!renamed) {
961                     kDebug() << "rename " << dir.filePath (files[i]) << "->" << m_grab_file;
962                     renamed = true;
963                     ::rename (dir.filePath (files[i]).toLocal8Bit().constData(),
964                             m_grab_file.toLocal8Bit ().constData ());
965                 } else {
966                     kDebug() << "rm " << files[i];
967                     dir.remove (files[i]);
968                 }
969             }
970             QString dirname = dir.dirName ();
971             dir.cdUp ();
972             kDebug() << m_grab_dir << " " << files.size () << " rmdir " << dirname;
973             dir.rmdir (dirname);
974         }
975         if (m_source && m_needs_restarted) {
976             commands.clear ();
977             int pos = m_source->position ();
978             play ();
979             seek (pos, true);
980             return;
981         }
982     }
983     setState (IProcess::Ready);
984 }
985 
setAudioLang(int id)986 void MPlayer::setAudioLang (int id) {
987     aid = id;
988     m_needs_restarted = true;
989     sendCommand (QString ("quit"));
990 }
991 
setSubtitle(int id)992 void MPlayer::setSubtitle (int id) {
993     sid = id;
994     m_needs_restarted = true;
995     sendCommand (QString ("quit"));
996 }
997 
998 //-----------------------------------------------------------------------------
999 
1000 extern const char * strMPlayerGroup;
1001 static const char * strMPlayerPatternGroup = "MPlayer Output Matching";
1002 static const char * strMPlayerPath = "MPlayer Path";
1003 static const char * strAddArgs = "Additional Arguments";
1004 static const char * strCacheSize = "Cache Size for Streaming";
1005 static const char * strAlwaysBuildIndex = "Always build index";
1006 static const int non_patterns = 4;
1007 
1008 static struct MPlayerPattern {
1009     QString caption;
1010     const char * name;
1011     const char * pattern;
1012 } _mplayer_patterns [] = {
1013     { i18n ("Size pattern"), "Movie Size", "VO:.*[^0-9]([0-9]+)x([0-9]+)" },
1014     { i18n ("Cache pattern"), "Cache Fill", "Cache fill:[^0-9]*([0-9\\.]+)%" },
1015     { i18n ("Position pattern"), "Movie Position", "[AV]:\\s*([0-9\\.]+)" },
1016     { i18n ("Index pattern"), "Index Pattern", "Generating Index: +([0-9]+)%" },
1017     { i18n ("Reference URL pattern"), "Reference URL Pattern", "Playing\\s+(.*[^\\.])\\.?\\s*$" },
1018     { i18n ("Reference pattern"), "Reference Pattern", "Reference Media file" },
1019     { i18n ("Start pattern"), "Start Playing", "Start[^ ]* play" },
1020     { i18n ("VCD track pattern"), "VCD Tracks", "track ([0-9]+):" },
1021     { i18n ("Audio CD tracks pattern"), "CDROM Tracks", "[Aa]udio CD[^0-9]+([0-9]+)[^0-9]tracks" }
1022 };
1023 
1024 namespace KMPlayer {
1025 
1026 class KMPLAYER_NO_EXPORT MPlayerPreferencesFrame : public QFrame {
1027 public:
1028     MPlayerPreferencesFrame (QWidget * parent);
1029     QTableWidget * table;
1030 };
1031 
1032 } // namespace
1033 
MPlayerPreferencesFrame(QWidget * parent)1034 KDE_NO_CDTOR_EXPORT MPlayerPreferencesFrame::MPlayerPreferencesFrame (QWidget * parent)
1035  : QFrame (parent) {
1036     QVBoxLayout * layout = new QVBoxLayout (this);
1037     table = new QTableWidget (int (MPlayerPreferencesPage::pat_last)+non_patterns, 2, this);
1038     table->verticalHeader ()->setVisible (false);
1039     table->horizontalHeader ()->setVisible (false);
1040     table->setContentsMargins (0, 0, 0, 0);
1041     table->setItem (0, 0, new QTableWidgetItem (i18n ("MPlayer command:")));
1042     table->setItem (0, 1, new QTableWidgetItem ());
1043     table->setItem (1, 0, new QTableWidgetItem (i18n ("Additional command line arguments:")));
1044     table->setItem (1, 1, new QTableWidgetItem ());
1045     table->setItem (2, 0, new QTableWidgetItem (QString("%1 (%2)").arg (i18n ("Cache size:")).arg (i18n ("kB")))); // FIXME for new translations
1046     QSpinBox* spin = new QSpinBox(table->viewport());
1047     spin->setMaximum(32767);
1048     spin->setSingleStep(32);
1049     table->setCellWidget (2, 1, spin);
1050     table->setItem (3, 0, new QTableWidgetItem (i18n ("Build new index when possible")));
1051     table->setCellWidget (3, 1, new QCheckBox (table->viewport()));
1052     table->cellWidget (3, 1)->setWhatsThis(i18n ("Allows seeking in indexed files (AVIs)"));
1053     for (int i = 0; i < int (MPlayerPreferencesPage::pat_last); i++) {
1054         table->setItem (i+non_patterns, 0, new QTableWidgetItem (_mplayer_patterns[i].caption));
1055         table->setItem (i+non_patterns, 1, new QTableWidgetItem ());
1056     }
1057     for (int i = 0; i < non_patterns + int (MPlayerPreferencesPage::pat_last); i++) {
1058         QTableWidgetItem *item = table->itemAt (i, 0);
1059         item->setFlags (item->flags () ^ Qt::ItemIsEditable);
1060     }
1061     table->horizontalHeader ()->setResizeMode (QHeaderView::ResizeToContents);
1062     table->horizontalHeader ()->setStretchLastSection (true);
1063     table->resizeRowsToContents ();
1064     layout->addWidget (table);
1065 }
1066 
MPlayerPreferencesPage()1067 KDE_NO_CDTOR_EXPORT MPlayerPreferencesPage::MPlayerPreferencesPage ()
1068  : m_configframe (0L) {
1069 }
1070 
write(KSharedConfigPtr config)1071 KDE_NO_EXPORT void MPlayerPreferencesPage::write (KSharedConfigPtr config) {
1072     KConfigGroup patterns_cfg (config, strMPlayerPatternGroup);
1073     for (int i = 0; i < int (pat_last); i++)
1074         patterns_cfg.writeEntry
1075             (_mplayer_patterns[i].name, m_patterns[i].pattern ());
1076     KConfigGroup mplayer_cfg (config, strMPlayerGroup);
1077     mplayer_cfg.writeEntry (strMPlayerPath, mplayer_path);
1078     mplayer_cfg.writeEntry (strAddArgs, additionalarguments);
1079     mplayer_cfg.writeEntry (strCacheSize, cachesize);
1080     mplayer_cfg.writeEntry (strAlwaysBuildIndex, alwaysbuildindex);
1081 }
1082 
read(KSharedConfigPtr config)1083 KDE_NO_EXPORT void MPlayerPreferencesPage::read (KSharedConfigPtr config) {
1084     KConfigGroup patterns_cfg (config, strMPlayerPatternGroup);
1085     for (int i = 0; i < int (pat_last); i++)
1086         m_patterns[i].setPattern (patterns_cfg.readEntry
1087                 (_mplayer_patterns[i].name, _mplayer_patterns[i].pattern));
1088     KConfigGroup mplayer_cfg (config, strMPlayerGroup);
1089     mplayer_path = mplayer_cfg.readEntry (strMPlayerPath, QString ("mplayer"));
1090     additionalarguments = mplayer_cfg.readEntry (strAddArgs, QString ());
1091     cachesize = mplayer_cfg.readEntry (strCacheSize, 384);
1092     alwaysbuildindex = mplayer_cfg.readEntry (strAlwaysBuildIndex, false);
1093 }
1094 
sync(bool fromUI)1095 KDE_NO_EXPORT void MPlayerPreferencesPage::sync (bool fromUI) {
1096     QTableWidget * table = m_configframe->table;
1097     QSpinBox * cacheSize = static_cast<QSpinBox *>(table->cellWidget (2, 1));
1098     QCheckBox * buildIndex = static_cast<QCheckBox *>(table->cellWidget (3, 1));
1099     if (fromUI) {
1100         mplayer_path = table->item (0, 1)->text ();
1101         additionalarguments = table->item (1, 1)->text ();
1102         for (int i = 0; i < int (pat_last); i++)
1103             m_patterns[i].setPattern (table->item (i+non_patterns, 1)->text ());
1104         cachesize = cacheSize->value();
1105         alwaysbuildindex = buildIndex->isChecked ();
1106     } else {
1107         table->item (0, 1)->setText (mplayer_path);
1108         table->item (1, 1)->setText (additionalarguments);
1109         for (int i = 0; i < int (pat_last); i++)
1110             table->item (i+non_patterns, 1)->setText (m_patterns[i].pattern ());
1111         if (cachesize > 0)
1112             cacheSize->setValue(cachesize);
1113         buildIndex->setChecked (alwaysbuildindex);
1114     }
1115 }
1116 
prefLocation(QString & item,QString & icon,QString & tab)1117 KDE_NO_EXPORT void MPlayerPreferencesPage::prefLocation (QString & item, QString & icon, QString & tab) {
1118     item = i18n ("General Options");
1119     icon = QString ("kmplayer");
1120     tab = i18n ("MPlayer");
1121 }
1122 
prefPage(QWidget * parent)1123 KDE_NO_EXPORT QFrame * MPlayerPreferencesPage::prefPage (QWidget * parent) {
1124     m_configframe = new MPlayerPreferencesFrame (parent);
1125     return m_configframe;
1126 }
1127 
1128 //-----------------------------------------------------------------------------
1129 
1130 static const char * mencoder_supports [] = {
1131     "dvdsource", "pipesource", "tvscanner", "tvsource", "urlsource",
1132     "vcdsource", "audiocdsource", NULL
1133 };
1134 
MEncoderProcessInfo(MediaManager * mgr)1135 MEncoderProcessInfo::MEncoderProcessInfo (MediaManager *mgr)
1136  : ProcessInfo ("mencoder", i18n ("M&Encoder"), mencoder_supports,
1137          mgr, NULL) {}
1138 
create(PartBase * part,ProcessUser * usr)1139 IProcess *MEncoderProcessInfo::create (PartBase *part, ProcessUser *usr) {
1140     MEncoder *m = new MEncoder (part, this, part->settings ());
1141     m->setSource (part->source ());
1142     m->user = usr;
1143     part->processCreated (m);
1144     return m;
1145 }
1146 
1147 KDE_NO_CDTOR_EXPORT
MEncoder(QObject * parent,ProcessInfo * pinfo,Settings * settings)1148 MEncoder::MEncoder (QObject * parent, ProcessInfo *pinfo, Settings * settings)
1149  : MPlayerBase (parent, pinfo, settings) {}
1150 
~MEncoder()1151 KDE_NO_CDTOR_EXPORT MEncoder::~MEncoder () {
1152 }
1153 
init()1154 KDE_NO_EXPORT void MEncoder::init () {
1155 }
1156 
deMediafiedPlay()1157 bool MEncoder::deMediafiedPlay () {
1158     stop ();
1159     RecordDocument *rd = recordDocument (user);
1160     if (!rd)
1161         return false;
1162     initProcess ();
1163     QString exe ("mencoder");
1164     QString margs = m_settings->mencoderarguments;
1165     if (m_settings->recordcopy)
1166         margs = QString ("-oac copy -ovc copy");
1167     QStringList args = KShell::splitArgs (margs);
1168     if (m_source)
1169         args << KShell::splitArgs (m_source->recordCmd ());
1170     // FIXME if (m_player->source () == source) // ugly
1171     //    m_player->stop ();
1172     QString myurl = encodeFileOrUrl (m_url);
1173     if (!myurl.isEmpty ())
1174         args << myurl;
1175     args << "-o" << encodeFileOrUrl (rd->record_file);
1176     startProcess (exe, args);
1177     qDebug ("mencoder %s\n", args.join (" ").toLocal8Bit ().constData ());
1178     if (m_process->waitForStarted ()) {
1179         setState (Playing);
1180         return true;
1181     }
1182     stop ();
1183     return false;
1184 }
1185 
stop()1186 KDE_NO_EXPORT void MEncoder::stop () {
1187     terminateJobs ();
1188     if (running ()) {
1189         kDebug () << "MEncoder::stop ()";
1190         Process::quit ();
1191         MPlayerBase::stop ();
1192     }
1193 }
1194 
1195 //-----------------------------------------------------------------------------
1196 
1197 static const char * mplayerdump_supports [] = {
1198     "dvdsource", "pipesource", "tvscanner", "tvsource", "urlsource", "vcdsource", "audiocdsource", 0L
1199 };
1200 
MPlayerDumpProcessInfo(MediaManager * mgr)1201 MPlayerDumpProcessInfo::MPlayerDumpProcessInfo (MediaManager *mgr)
1202  : ProcessInfo ("mplayerdumpstream", i18n ("&MPlayerDumpstream"),
1203          mplayerdump_supports, mgr, NULL) {}
1204 
create(PartBase * p,ProcessUser * usr)1205 IProcess *MPlayerDumpProcessInfo::create (PartBase *p, ProcessUser *usr) {
1206     MPlayerDumpstream *m = new MPlayerDumpstream (p, this, p->settings ());
1207     m->setSource (p->source ());
1208     m->user = usr;
1209     p->processCreated (m);
1210     return m;
1211 }
1212 
1213 KDE_NO_CDTOR_EXPORT
MPlayerDumpstream(QObject * p,ProcessInfo * pi,Settings * s)1214 MPlayerDumpstream::MPlayerDumpstream (QObject *p, ProcessInfo *pi, Settings *s)
1215  : MPlayerBase (p, pi, s) {}
1216 
~MPlayerDumpstream()1217 KDE_NO_CDTOR_EXPORT MPlayerDumpstream::~MPlayerDumpstream () {
1218 }
1219 
init()1220 KDE_NO_EXPORT void MPlayerDumpstream::init () {
1221 }
1222 
deMediafiedPlay()1223 bool MPlayerDumpstream::deMediafiedPlay () {
1224     stop ();
1225     RecordDocument *rd = recordDocument (user);
1226     if (!rd)
1227         return false;
1228     initProcess ();
1229     QString exe ("mplayer");
1230     QStringList args;
1231     args << KShell::splitArgs (m_source->recordCmd ());
1232     // FIXME if (m_player->source () == source) // ugly
1233     //    m_player->stop ();
1234     QString myurl = encodeFileOrUrl (m_url);
1235     if (!myurl.isEmpty ())
1236         args << myurl;
1237     args << "-dumpstream" << "-dumpfile" << encodeFileOrUrl (rd->record_file);
1238     qDebug ("mplayer %s\n", args.join (" ").toLocal8Bit ().constData ());
1239     startProcess (exe, args);
1240     if (m_process->waitForStarted ()) {
1241         setState (Playing);
1242         return true;
1243     }
1244     stop ();
1245     return false;
1246 }
1247 
stop()1248 KDE_NO_EXPORT void MPlayerDumpstream::stop () {
1249     terminateJobs ();
1250     if (!m_source || !running ())
1251         return;
1252     kDebug () << "MPlayerDumpstream::stop";
1253     if (running ())
1254         Process::quit ();
1255     MPlayerBase::stop ();
1256 }
1257 
1258 //-----------------------------------------------------------------------------
1259 
MasterProcessInfo(const char * nm,const QString & lbl,const char ** supported,MediaManager * mgr,PreferencesPage * pp)1260 MasterProcessInfo::MasterProcessInfo (const char *nm, const QString &lbl,
1261             const char **supported, MediaManager *mgr, PreferencesPage *pp)
1262  : ProcessInfo (nm, lbl, supported, mgr, pp),
1263    m_slave (NULL) {}
1264 
~MasterProcessInfo()1265 MasterProcessInfo::~MasterProcessInfo () {
1266     stopSlave ();
1267 }
1268 
initSlave()1269 void MasterProcessInfo::initSlave () {
1270     if (m_path.isEmpty ()) {
1271         static int count = 0;
1272         m_path = QString ("/master_%1").arg (count++);
1273         (void) new MasterAdaptor (this);
1274         QDBusConnection::sessionBus().registerObject (m_path, this);
1275         m_service = QDBusConnection::sessionBus().baseService ();
1276     }
1277     setupProcess (&m_slave);
1278     connect (m_slave, SIGNAL (finished (int, QProcess::ExitStatus)),
1279             this, SLOT (slaveStopped (int, QProcess::ExitStatus)));
1280     connect (m_slave, SIGNAL (readyReadStandardOutput ()),
1281             this, SLOT (slaveOutput ()));
1282     connect (m_slave, SIGNAL (readyReadStandardError ()),
1283             this, SLOT (slaveOutput ()));
1284 }
1285 
quitProcesses()1286 void MasterProcessInfo::quitProcesses () {
1287     stopSlave ();
1288 }
1289 
stopSlave()1290 void MasterProcessInfo::stopSlave () {
1291     if (!m_slave_service.isEmpty ()) {
1292         QDBusMessage msg = QDBusMessage::createMethodCall (
1293                 m_slave_service, QString ("/%1").arg (ProcessInfo::name),
1294                 "org.kde.kmplayer.Slave", "quit");
1295         //msg << m_url << mime << plugin << param_len;
1296         msg.setDelayedReply (false);
1297         QDBusConnection::sessionBus().send (msg);
1298     }
1299     if (processRunning (m_slave)) {
1300         m_slave->waitForFinished (1000);
1301         killProcess (m_slave, manager->player ()->view ());
1302     }
1303 }
1304 
running(const QString & srv)1305 void MasterProcessInfo::running (const QString &srv) {
1306     kDebug() << "MasterProcessInfo::running " << srv;
1307     m_slave_service = srv;
1308     MediaManager::ProcessList &pl = manager->processes ();
1309     const MediaManager::ProcessList::iterator e = pl.end ();
1310     for (MediaManager::ProcessList::iterator i = pl.begin (); i != e; ++i)
1311         if (this == (*i)->process_info)
1312             static_cast <Process *> (*i)->setState (IProcess::Ready);
1313 }
1314 
slaveStopped(int,QProcess::ExitStatus)1315 void MasterProcessInfo::slaveStopped (int, QProcess::ExitStatus) {
1316     m_slave_service.truncate (0);
1317     MediaManager::ProcessList &pl = manager->processes ();
1318     const MediaManager::ProcessList::iterator e = pl.end ();
1319     for (MediaManager::ProcessList::iterator i = pl.begin (); i != e; ++i)
1320         if (this == (*i)->process_info)
1321             static_cast <Process *> (*i)->setState (IProcess::NotRunning);
1322 }
1323 
slaveOutput()1324 void MasterProcessInfo::slaveOutput () {
1325     outputToView(manager->player()->viewWidget(), m_slave->readAllStandardOutput());
1326     outputToView(manager->player()->viewWidget(), m_slave->readAllStandardError ());
1327 }
1328 
MasterProcess(QObject * parent,ProcessInfo * pinfo,Settings * settings)1329 MasterProcess::MasterProcess (QObject *parent, ProcessInfo *pinfo, Settings *settings)
1330  : Process (parent, pinfo, settings) {}
1331 
~MasterProcess()1332 MasterProcess::~MasterProcess () {
1333 }
1334 
init()1335 void MasterProcess::init () {
1336 }
1337 
deMediafiedPlay()1338 bool MasterProcess::deMediafiedPlay () {
1339     WindowId wid = user->viewer ()->windowHandle ();
1340     m_slave_path = QString ("/stream_%1").arg (wid);
1341     MasterProcessInfo *mpi = static_cast <MasterProcessInfo *>(process_info);
1342     kDebug() << "MasterProcess::deMediafiedPlay " << m_url << " " << wid;
1343 
1344     (void) new StreamMasterAdaptor (this);
1345     QDBusConnection::sessionBus().registerObject (
1346             QString ("%1/stream_%2").arg (mpi->m_path).arg (wid), this);
1347 
1348     QDBusMessage msg = QDBusMessage::createMethodCall (
1349             mpi->m_slave_service, QString ("/%1").arg (process_info->name),
1350                 "org.kde.kmplayer.Slave", "newStream");
1351     if (!m_url.startsWith ("dvd:") ||
1352             !m_url.startsWith ("vcd:") ||
1353             !m_url.startsWith ("cdda:")) {
1354         KUrl url (m_url);
1355         if (url.isLocalFile ())
1356             m_url = getPath (url);
1357     }
1358     msg << m_url << (qulonglong)wid;
1359     msg.setDelayedReply (false);
1360     QDBusConnection::sessionBus().send (msg);
1361     setState (IProcess::Buffering);
1362     return true;
1363 }
1364 
running() const1365 bool MasterProcess::running () const {
1366     MasterProcessInfo *mpi = static_cast <MasterProcessInfo *>(process_info);
1367     return processRunning (mpi->m_slave);
1368 }
1369 
loading(int perc)1370 void MasterProcess::loading (int perc) {
1371     process_info->manager->player ()->setLoaded (perc);
1372 }
1373 
streamInfo(uint64_t length,double aspect)1374 void MasterProcess::streamInfo (uint64_t length, double aspect) {
1375     kDebug() << length;
1376     m_source->setLength (mrl (), length);
1377     m_source->setAspect (mrl (), aspect);
1378 }
1379 
streamMetaInfo(QString info)1380 void MasterProcess::streamMetaInfo (QString info) {
1381     m_source->document ()->message (MsgInfoString, &info);
1382 }
1383 
playing()1384 void MasterProcess::playing () {
1385     process_info->manager->player ()->setLoaded (100);
1386     setState (IProcess::Playing);
1387 }
1388 
progress(uint64_t pos)1389 void MasterProcess::progress (uint64_t pos) {
1390     m_source->setPosition (pos);
1391 }
1392 
pause()1393 void MasterProcess::pause () {
1394     if (IProcess::Playing == m_state) {
1395         MasterProcessInfo *mpi = static_cast<MasterProcessInfo *>(process_info);
1396         QDBusMessage msg = QDBusMessage::createMethodCall (
1397                 mpi->m_slave_service,
1398                 m_slave_path,
1399                 "org.kde.kmplayer.StreamSlave",
1400                 "pause");
1401         msg.setDelayedReply (false);
1402         QDBusConnection::sessionBus().send (msg);
1403     }
1404 }
1405 
unpause()1406 void MasterProcess::unpause () {
1407     pause ();
1408 }
1409 
seek(int pos,bool)1410 bool MasterProcess::seek (int pos, bool) {
1411     if (IProcess::Playing == m_state) {
1412         MasterProcessInfo *mpi = static_cast<MasterProcessInfo *>(process_info);
1413         QDBusMessage msg = QDBusMessage::createMethodCall (
1414                 mpi->m_slave_service,
1415                 m_slave_path,
1416                 "org.kde.kmplayer.StreamSlave",
1417                 "seek");
1418         msg << (qulonglong) pos << true;
1419         msg.setDelayedReply (false);
1420         QDBusConnection::sessionBus().send (msg);
1421         return true;
1422     }
1423     return false;
1424 }
1425 
volume(int incdec,bool)1426 KDE_NO_EXPORT void MasterProcess::volume (int incdec, bool) {
1427     if (IProcess::Playing == m_state) {
1428         MasterProcessInfo *mpi = static_cast<MasterProcessInfo *>(process_info);
1429         QDBusMessage msg = QDBusMessage::createMethodCall (
1430                 mpi->m_slave_service,
1431                 m_slave_path,
1432                 "org.kde.kmplayer.StreamSlave",
1433                 "volume");
1434         msg << incdec;
1435         msg.setDelayedReply (false);
1436         QDBusConnection::sessionBus().send (msg);
1437     }
1438 }
1439 
eof()1440 void MasterProcess::eof () {
1441     setState (IProcess::Ready);
1442 }
1443 
stop()1444 void MasterProcess::stop () {
1445     if (m_state > IProcess::Ready) {
1446         MasterProcessInfo *mpi = static_cast<MasterProcessInfo *>(process_info);
1447         QDBusMessage msg = QDBusMessage::createMethodCall (
1448                 mpi->m_slave_service,
1449                 m_slave_path,
1450                 "org.kde.kmplayer.StreamSlave",
1451                 "stop");
1452         msg.setDelayedReply (false);
1453         QDBusConnection::sessionBus().send (msg);
1454     }
1455 }
1456 
1457 //-------------------------%<--------------------------------------------------
1458 
1459 static const char *phonon_supports [] = {
1460     "urlsource", "dvdsource", "vcdsource", "audiocdsource", 0L
1461 };
1462 
PhononProcessInfo(MediaManager * mgr)1463 PhononProcessInfo::PhononProcessInfo (MediaManager *mgr)
1464   : MasterProcessInfo ("phonon", i18n ("&Phonon"), phonon_supports, mgr, NULL)
1465 {}
1466 
create(PartBase * part,ProcessUser * usr)1467 IProcess *PhononProcessInfo::create (PartBase *part, ProcessUser *usr) {
1468     if (!processRunning (m_slave))
1469         startSlave ();
1470     Phonon *p = new Phonon (part, this, part->settings ());
1471     p->setSource (part->source ());
1472     p->user = usr;
1473     part->processCreated (p);
1474     return p;
1475 }
1476 
startSlave()1477 bool PhononProcessInfo::startSlave () {
1478     initSlave ();
1479     QString exe ("kphononplayer");
1480     QStringList args;
1481     args << "-cb" << (m_service + m_path);
1482     qDebug ("kphononplayer %s", args.join (" ").toLocal8Bit ().constData ());
1483     m_slave->start (exe, args);
1484     return true;
1485 }
1486 
Phonon(QObject * parent,ProcessInfo * pinfo,Settings * settings)1487 Phonon::Phonon (QObject *parent, ProcessInfo *pinfo, Settings *settings)
1488  : MasterProcess (parent, pinfo, settings) {}
1489 
ready()1490 bool Phonon::ready () {
1491     if (user && user->viewer ())
1492         user->viewer ()->useIndirectWidget (false);
1493     kDebug() << "Phonon::ready " << state () << endl;
1494     PhononProcessInfo *ppi = static_cast <PhononProcessInfo *>(process_info);
1495     if (running ()) {
1496         if (!ppi->m_slave_service.isEmpty ())
1497             setState (IProcess::Ready);
1498         return true;
1499     } else {
1500         return ppi->startSlave ();
1501     }
1502 }
1503 
1504 //-----------------------------------------------------------------------------
1505 
ConfigDocument()1506 KDE_NO_CDTOR_EXPORT ConfigDocument::ConfigDocument ()
1507     : Document (QString ()) {}
1508 
~ConfigDocument()1509 KDE_NO_CDTOR_EXPORT ConfigDocument::~ConfigDocument () {
1510     kDebug () << "~ConfigDocument";
1511 }
1512 
1513 namespace KMPlayer {
1514     /*
1515      * Element for ConfigDocument
1516      */
1517     struct KMPLAYER_NO_EXPORT SomeNode : public ConfigNode {
SomeNodeKMPlayer::SomeNode1518         KDE_NO_CDTOR_EXPORT SomeNode (NodePtr & d, const QString & t)
1519             : ConfigNode (d, t) {}
~SomeNodeKMPlayer::SomeNode1520         KDE_NO_CDTOR_EXPORT ~SomeNode () {}
1521         Node *childFromTag (const QString & t);
1522     };
1523 } // namespace
1524 
ConfigNode(NodePtr & d,const QString & t)1525 KDE_NO_CDTOR_EXPORT ConfigNode::ConfigNode (NodePtr & d, const QString & t)
1526     : DarkNode (d, t.toUtf8 ()), w (0L) {}
1527 
childFromTag(const QString & tag)1528 Node *ConfigDocument::childFromTag (const QString & tag) {
1529     if (tag.toLower () == QString ("document"))
1530         return new ConfigNode (m_doc, tag);
1531     return 0L;
1532 }
1533 
childFromTag(const QString & t)1534 Node *ConfigNode::childFromTag (const QString & t) {
1535     return new TypeNode (m_doc, t);
1536 }
1537 
TypeNode(NodePtr & d,const QString & t)1538 KDE_NO_CDTOR_EXPORT TypeNode::TypeNode (NodePtr & d, const QString & t)
1539  : ConfigNode (d, t), tag (t) {}
1540 
childFromTag(const QString & tag)1541 Node *TypeNode::childFromTag (const QString & tag) {
1542     return new SomeNode (m_doc, tag);
1543 }
1544 
childFromTag(const QString & t)1545 Node *SomeNode::childFromTag (const QString & t) {
1546     return new SomeNode (m_doc, t);
1547 }
1548 
createWidget(QWidget * parent)1549 QWidget * TypeNode::createWidget (QWidget * parent) {
1550     QByteArray ba = getAttribute (Ids::attr_type).toAscii ();
1551     const char *ctype = ba.constData ();
1552     QString value = getAttribute (Ids::attr_value);
1553     if (!strcmp (ctype, "range")) {
1554         QSlider* slider = new QSlider (parent);
1555         slider->setMinimum(getAttribute (QString ("START")).toInt ());
1556         slider->setMaximum(getAttribute (Ids::attr_end).toInt ());
1557         slider->setPageStep(1);
1558         slider->setOrientation(Qt::Horizontal);
1559         slider->setValue(value.toInt ());
1560         w = slider;
1561     } else if (!strcmp (ctype, "num") || !strcmp (ctype,  "string")) {
1562         w = new QLineEdit (value, parent);
1563     } else if (!strcmp (ctype, "bool")) {
1564         QCheckBox * checkbox = new QCheckBox (parent);
1565         checkbox->setChecked (value.toInt ());
1566         w = checkbox;
1567     } else if (!strcmp (ctype, "enum")) {
1568         QComboBox * combo = new QComboBox (parent);
1569         for (Node *e = firstChild (); e; e = e->nextSibling ())
1570             if (e->isElementNode () && !strcmp (e->nodeName (), "item"))
1571                 combo->addItem (static_cast <Element *> (e)->getAttribute (Ids::attr_value));
1572         combo->setCurrentIndex (value.toInt ());
1573         w = combo;
1574     } else if (!strcmp (ctype, "tree")) {
1575     } else
1576         kDebug() << "Unknown type:" << ctype;
1577     return w;
1578 }
1579 
changedXML(QTextStream & out)1580 void TypeNode::changedXML (QTextStream & out) {
1581     if (!w) return;
1582     QByteArray ba = getAttribute (Ids::attr_type).toAscii ();
1583     const char *ctype = ba.constData ();
1584     QString value = getAttribute (Ids::attr_value);
1585     QString newvalue;
1586     if (!strcmp (ctype, "range")) {
1587         newvalue = QString::number (static_cast <QSlider *> (w)->value ());
1588     } else if (!strcmp (ctype, "num") || !strcmp (ctype,  "string")) {
1589         newvalue = static_cast <QLineEdit *> (w)->text ();
1590     } else if (!strcmp (ctype, "bool")) {
1591         newvalue = QString::number (static_cast <QCheckBox *> (w)->isChecked());
1592     } else if (!strcmp (ctype, "enum")) {
1593         newvalue = QString::number (static_cast<QComboBox *>(w)->currentIndex());
1594     } else if (!strcmp (ctype, "tree")) {
1595     } else
1596         kDebug() << "Unknown type:" << ctype;
1597     if (value != newvalue) {
1598         value = newvalue;
1599         setAttribute (Ids::attr_value, newvalue);
1600         out << outerXML ();
1601     }
1602 }
1603 
1604 //-----------------------------------------------------------------------------
1605 
1606 static const char * ffmpeg_supports [] = {
1607     "tvsource", "urlsource", 0L
1608 };
1609 
FFMpegProcessInfo(MediaManager * mgr)1610 FFMpegProcessInfo::FFMpegProcessInfo (MediaManager *mgr)
1611  : ProcessInfo ("ffmpeg", i18n ("&FFMpeg"), ffmpeg_supports, mgr, NULL) {}
1612 
create(PartBase * p,ProcessUser * usr)1613 IProcess *FFMpegProcessInfo::create (PartBase *p, ProcessUser *usr) {
1614     FFMpeg *m = new FFMpeg (p, this, p->settings ());
1615     m->setSource (p->source ());
1616     m->user = usr;
1617     p->processCreated (m);
1618     return m;
1619 }
1620 
FFMpeg(QObject * parent,ProcessInfo * pinfo,Settings * settings)1621 FFMpeg::FFMpeg (QObject *parent, ProcessInfo *pinfo, Settings * settings)
1622  : Process (parent, pinfo, settings) {
1623 }
1624 
~FFMpeg()1625 KDE_NO_CDTOR_EXPORT FFMpeg::~FFMpeg () {
1626 }
1627 
init()1628 KDE_NO_EXPORT void FFMpeg::init () {
1629 }
1630 
deMediafiedPlay()1631 bool FFMpeg::deMediafiedPlay () {
1632     RecordDocument *rd = recordDocument (user);
1633     if (!rd)
1634         return false;
1635     initProcess ();
1636     connect (m_process, SIGNAL (finished (int, QProcess::ExitStatus)),
1637             this, SLOT (processStopped (int, QProcess::ExitStatus)));
1638     QString outurl = encodeFileOrUrl (rd->record_file);
1639     if (outurl.startsWith (QChar ('/')))
1640         QFile (outurl).remove ();
1641     QString exe ("ffmpeg ");
1642     QStringList args;
1643     if (!m_source->videoDevice ().isEmpty () ||
1644         !m_source->audioDevice ().isEmpty ()) {
1645         if (!m_source->videoDevice ().isEmpty ())
1646             args << "-vd" << m_source->videoDevice ();
1647         else
1648             args << "-vn";
1649         if (!m_source->audioDevice ().isEmpty ())
1650             args << "-ad" << m_source->audioDevice ();
1651         else
1652             args << "-an";
1653         QProcess process;
1654         QString ctl_exe ("v4lctl");
1655         QStringList ctl_args;
1656         if (!m_source->videoNorm ().isEmpty ()) {
1657             ctl_args << "-c" << m_source->videoDevice () << "setnorm" << m_source->videoNorm ();
1658             process.start (ctl_exe, ctl_args);
1659             process.waitForFinished (5000);
1660             args << "-tvstd" << m_source->videoNorm ();
1661         }
1662         if (m_source->frequency () > 0) {
1663             ctl_args.clear ();
1664             ctl_args << "-c" << m_source->videoDevice () << "setfreq" << QString::number (m_source->frequency ());
1665             process.start (ctl_exe, ctl_args);
1666             process.waitForFinished (5000);
1667         }
1668     } else {
1669         args << "-i" << encodeFileOrUrl (m_url);
1670     }
1671     args << KShell::splitArgs (m_settings->ffmpegarguments);
1672     args << outurl;
1673     qDebug ("ffmpeg %s\n", args.join (" ").toLocal8Bit().constData ());
1674     // FIXME if (m_player->source () == source) // ugly
1675     //    m_player->stop ();
1676     m_process->start (exe, args);
1677     if (m_process->waitForStarted ()) {
1678         setState (Playing);
1679         return true;
1680     }
1681     stop ();
1682     return false;
1683 }
1684 
stop()1685 KDE_NO_EXPORT void FFMpeg::stop () {
1686     terminateJobs ();
1687     if (!running ())
1688         return;
1689     kDebug () << "FFMpeg::stop";
1690     m_process->write ("q");
1691 }
1692 
quit()1693 KDE_NO_EXPORT void FFMpeg::quit () {
1694     stop ();
1695     if (!running ())
1696         return;
1697     if (m_process->waitForFinished (2000))
1698         Process::quit ();
1699 }
1700 
processStopped(int,QProcess::ExitStatus)1701 KDE_NO_EXPORT void FFMpeg::processStopped (int, QProcess::ExitStatus) {
1702     setState (IProcess::NotRunning);
1703 }
1704 
1705 //-----------------------------------------------------------------------------
1706 
1707 static const char *npp_supports [] = { "urlsource", 0L };
1708 
NppProcessInfo(MediaManager * mgr)1709 NppProcessInfo::NppProcessInfo (MediaManager *mgr)
1710  : ProcessInfo ("npp", i18n ("&Ice Ape"), npp_supports, mgr, NULL) {}
1711 
create(PartBase * p,ProcessUser * usr)1712 IProcess *NppProcessInfo::create (PartBase *p, ProcessUser *usr) {
1713     NpPlayer *n = new NpPlayer (p, this, p->settings());
1714     n->setSource (p->source ());
1715     n->user = usr;
1716     p->processCreated (n);
1717     return n;
1718 }
1719 
1720 #ifdef KMPLAYER_WITH_NPP
1721 
NpStream(NpPlayer * p,uint32_t sid,const QString & u,const QByteArray & ps)1722 KDE_NO_CDTOR_EXPORT NpStream::NpStream (NpPlayer *p, uint32_t sid, const QString &u, const QByteArray &ps)
1723  : QObject (p),
1724    url (u),
1725    post (ps),
1726    job (0L), bytes (0),
1727    stream_id (sid),
1728    content_length (0),
1729    finish_reason (NoReason),
1730    received_data (false) {
1731     data_arrival.tv_sec = 0;
1732     (void) new StreamAdaptor (this);
1733     QString objpath = QString ("%1/stream_%2").arg (p->objectPath ()).arg (sid);
1734     QDBusConnection::sessionBus().registerObject (objpath, this);
1735 }
1736 
~NpStream()1737 KDE_NO_CDTOR_EXPORT NpStream::~NpStream () {
1738     close ();
1739 }
1740 
open()1741 KDE_NO_EXPORT void NpStream::open () {
1742     kDebug () << "NpStream " << stream_id << " open " << url;
1743     if (url.startsWith ("javascript:")) {
1744         NpPlayer *npp = static_cast <NpPlayer *> (parent ());
1745         QString result = npp->evaluate (url.mid (11), false);
1746         if (!result.isEmpty ()) {
1747             QByteArray cr = result.toLocal8Bit ();
1748             int len = strlen (cr.constData ());
1749             pending_buf.resize (len + 1);
1750             memcpy (pending_buf.data (), cr.constData (), len);
1751             pending_buf.data ()[len] = 0;
1752             gettimeofday (&data_arrival, 0L);
1753         }
1754         kDebug () << "result is " << pending_buf.constData ();
1755         finish_reason = BecauseDone;
1756         emit stateChanged ();
1757     } else {
1758         if (!post.size ()) {
1759             job = KIO::get (KUrl (url), KIO::NoReload, KIO::HideProgressInfo);
1760             job->addMetaData ("PropagateHttpHeader", "true");
1761         } else {
1762             QStringList name;
1763             QStringList value;
1764             QString buf;
1765             int data_pos = -1;
1766             for (int i = 0; i < post.size () && data_pos < 0; ++i) {
1767                 char c = post.at (i);
1768                 switch (c) {
1769                 case ':':
1770                     if (name.size () == value.size ()) {
1771                         name << buf;
1772                         buf.truncate (0);
1773                     } else
1774                         buf += QChar (':');
1775                     break;
1776                 case '\r':
1777                     break;
1778                 case '\n':
1779                     if (name.size () == value.size ()) {
1780                         if (buf.isEmpty ()) {
1781                             data_pos = i + 1;
1782                         } else {
1783                             name << buf;
1784                             value << QString ("");
1785                         }
1786                     } else {
1787                         value << buf;
1788                     }
1789                     buf.truncate (0);
1790                     break;
1791                 default:
1792                     buf += QChar (c);
1793                 }
1794             }
1795             job = KIO::http_post (KUrl (url), post.mid (data_pos), KIO::HideProgressInfo);
1796             for (int i = 0; i < name.size (); ++i)
1797                 job->addMetaData (name[i].trimmed (), value[i].trimmed ());
1798         }
1799         job->addMetaData ("errorPage", "false");
1800         connect (job, SIGNAL (data (KIO::Job *, const QByteArray &)),
1801                 this, SLOT (slotData (KIO::Job *, const QByteArray &)));
1802         connect (job, SIGNAL (result (KJob *)),
1803                 this, SLOT (slotResult (KJob *)));
1804         connect (job, SIGNAL(redirection(KIO::Job*, const QUrl&)),
1805                 this, SLOT (redirection (KIO::Job *, const QUrl &)));
1806         connect (job, SIGNAL (mimetype (KIO::Job *, const QString &)),
1807                 SLOT (slotMimetype (KIO::Job *, const QString &)));
1808         connect (job, SIGNAL (totalSize (KJob *, qulonglong)),
1809                 SLOT (slotTotalSize (KJob *, qulonglong)));
1810     }
1811 }
1812 
close()1813 KDE_NO_EXPORT void NpStream::close () {
1814     if (job) {
1815         job->kill (); // quiet, no result signal
1816         job = 0L;
1817         finish_reason = BecauseStopped;
1818         // don't emit stateChanged(), because always triggered from NpPlayer
1819     }
1820 }
1821 
destroy()1822 KDE_NO_EXPORT void NpStream::destroy () {
1823     pending_buf.clear ();
1824     static_cast <NpPlayer *> (parent ())->destroyStream (stream_id);
1825 }
1826 
slotResult(KJob * jb)1827 KDE_NO_EXPORT void NpStream::slotResult (KJob *jb) {
1828     kDebug() << "slotResult " << stream_id << " " << bytes << " err:" << jb->error ();
1829     finish_reason = jb->error () ? BecauseError : BecauseDone;
1830     job = 0L; // signal KIO::Job::result deletes itself
1831     emit stateChanged ();
1832 }
1833 
slotData(KIO::Job *,const QByteArray & qb)1834 KDE_NO_EXPORT void NpStream::slotData (KIO::Job*, const QByteArray& qb) {
1835     if (job) {
1836         int sz = pending_buf.size ();
1837         if (sz) {
1838             pending_buf.resize (sz + qb.size ());
1839             memcpy (pending_buf.data () + sz, qb.constData (), qb.size ());
1840         } else {
1841             pending_buf = qb;
1842         }
1843         if (sz + qb.size () > 64000 &&
1844                 !job->isSuspended () && !job->suspend ())
1845             kError () << "suspend not supported" << endl;
1846         if (!sz)
1847             gettimeofday (&data_arrival, 0L);
1848         if (!received_data) {
1849             received_data = true;
1850             http_headers = job->queryMetaData ("HTTP-Headers");
1851             if (!http_headers.isEmpty() && !http_headers.endsWith (QChar ('\n')))
1852                 http_headers += QChar ('\n');
1853         }
1854         if (sz + qb.size ())
1855             emit stateChanged ();
1856     }
1857 }
1858 
redirection(KIO::Job *,const QUrl & kurl)1859 KDE_NO_EXPORT void NpStream::redirection (KIO::Job*, const QUrl& kurl) {
1860     url = kurl.url ();
1861     emit redirected (stream_id, kurl);
1862 }
1863 
slotMimetype(KIO::Job *,const QString & mime)1864 void NpStream::slotMimetype (KIO::Job *, const QString &mime) {
1865     mimetype = mime.indexOf("adobe.flash") > -1 ? "application/x-shockwave-flash" : mime;
1866 }
1867 
slotTotalSize(KJob *,qulonglong sz)1868 void NpStream::slotTotalSize (KJob *, qulonglong sz) {
1869     content_length = sz;
1870 }
1871 
1872 KDE_NO_CDTOR_EXPORT
NpPlayer(QObject * parent,ProcessInfo * pinfo,Settings * settings)1873 NpPlayer::NpPlayer (QObject *parent, ProcessInfo *pinfo, Settings *settings)
1874  : Process (parent, pinfo, settings),
1875    write_in_progress (false),
1876    in_process_stream (false) {
1877 }
1878 
~NpPlayer()1879 KDE_NO_CDTOR_EXPORT NpPlayer::~NpPlayer () {
1880 }
1881 
init()1882 KDE_NO_EXPORT void NpPlayer::init () {
1883 }
1884 
initProcess()1885 KDE_NO_EXPORT void NpPlayer::initProcess () {
1886     setupProcess (&m_process);
1887     m_process_state = QProcess::NotRunning;
1888     connect (m_process, SIGNAL (finished (int, QProcess::ExitStatus)),
1889             this, SLOT (processStopped (int, QProcess::ExitStatus)));
1890     connect (m_process, SIGNAL (readyReadStandardError ()),
1891             this, SLOT (processOutput ()));
1892     connect (m_process, SIGNAL (bytesWritten (qint64)),
1893             this, SLOT (wroteStdin (qint64)));
1894     if (iface.isEmpty ()) {
1895         iface = QString ("org.kde.kmplayer.callback");
1896         static int count = 0;
1897         path = QString ("/npplayer%1").arg (count++);
1898         (void) new CallbackAdaptor (this);
1899         QDBusConnection::sessionBus().registerObject (path, this);
1900         filter = QString ("type='method_call',interface='org.kde.kmplayer.callback'");
1901         service = QDBusConnection::sessionBus().baseService ();
1902         //service = QString (dbus_bus_get_unique_name (conn));
1903         kDebug() << "using service " << service << " interface " << iface << " filter:" << filter;
1904     }
1905 }
1906 
deMediafiedPlay()1907 KDE_NO_EXPORT bool NpPlayer::deMediafiedPlay () {
1908     kDebug() << "NpPlayer::play '" << m_url << "' state " << m_state;
1909     // if we change from XPLAIN to XEMBED, the DestroyNotify may come later
1910     if (!view ())
1911         return false;
1912     if (!m_url.isEmpty () && m_url != "about:empty") {
1913         QDBusMessage msg = QDBusMessage::createMethodCall (
1914                 remote_service, "/plugin", "org.kde.kmplayer.backend", "play");
1915         msg << m_url;
1916         msg.setDelayedReply (false);
1917         QDBusConnection::sessionBus().send (msg);
1918         setState (IProcess::Buffering);
1919     }
1920     return true;
1921 }
1922 
ready()1923 KDE_NO_EXPORT bool NpPlayer::ready () {
1924     Mrl *node = mrl ();
1925     if (!node || !user || !user->viewer ())
1926         return false;
1927 
1928     user->viewer ()->useIndirectWidget (false);
1929     user->viewer ()->setMonitoring (IViewer::MonitorNothing);
1930 
1931     if (state () == IProcess::Ready)
1932         return true;
1933 
1934     initProcess ();
1935     QString exe ("knpplayer");
1936     QStringList args;
1937     args << "-cb" << (service + path);
1938     args << "-wid" << QString::number (user->viewer ()->windowHandle ());
1939     startProcess (exe, args);
1940     if (m_process->waitForStarted (5000)) {
1941         QString s;
1942         for (int i = 0; i < 2 && remote_service.isEmpty (); ++i) {
1943             if (!m_process->waitForReadyRead (5000))
1944                 return false;
1945             const QByteArray ba = m_process->readAllStandardOutput ();
1946             s += QString::fromAscii (ba.data (), ba.size ());
1947             int nl = s.indexOf (QChar ('\n'));
1948             if (nl > 0) {
1949                 int p = s.indexOf ("NPP_DBUS_SRV=");
1950                 if (p > -1)
1951                     remote_service = s.mid (p + 13, nl - p - 13);
1952             }
1953         }
1954     }
1955     connect (m_process, SIGNAL (readyReadStandardOutput ()),
1956             this, SLOT (processOutput ()));
1957     if (!remote_service.isEmpty ()) {
1958         QString mime = "text/plain";
1959         QString plugin;
1960         Element *elm = node;
1961         if (elm->id == id_node_html_object) {
1962             // this sucks to have to do this here ..
1963             for (Node *n = elm->firstChild (); n; n = n->nextSibling ())
1964                 if (n->id == KMPlayer::id_node_html_embed) {
1965                     elm = static_cast <Element *> (n);
1966                     break;
1967                 }
1968         }
1969         for (Node *n = mrl (); n; n = n->parentNode ()) {
1970             Mrl *mrl = n->mrl ();
1971             if (mrl && !mrl->mimetype.isEmpty ()) {
1972                 plugin = m_source->plugin (mrl->mimetype);
1973                 kDebug() << "search plugin " << mrl->mimetype << "->" << plugin;
1974                 if (!plugin.isEmpty ()) {
1975                     mime = mrl->mimetype;
1976                     if ( mime.indexOf("adobe.flash") > -1 )
1977                         mime = "application/x-shockwave-flash";
1978                     break;
1979                 }
1980             }
1981         }
1982         if (!plugin.isEmpty ()) {
1983             QDBusMessage msg = QDBusMessage::createMethodCall (
1984                     remote_service, "/plugin", "org.kde.kmplayer.backend", "setup");
1985             msg << mime << plugin;
1986             QMap <QString, QVariant> urlargs;
1987             for (AttributePtr a = elm->attributes ().first (); a; a = a->nextSibling ())
1988                 urlargs.insert (a->name ().toString (), a->value ());
1989             msg << urlargs;
1990             msg.setDelayedReply (false);
1991             QDBusConnection::sessionBus().call (msg, QDBus::BlockWithGui);
1992             setState (IProcess::Ready);
1993             return true;
1994         }
1995     }
1996     m_old_state = m_state = Ready;
1997     stop ();
1998 
1999     return false;
2000 }
2001 
running(const QString & srv)2002 KDE_NO_EXPORT void NpPlayer::running (const QString &srv) {
2003     remote_service = srv;
2004     kDebug () << "NpPlayer::running " << srv;
2005     setState (Ready);
2006 }
2007 
plugged()2008 void NpPlayer::plugged () {
2009     view ()->videoStart ();
2010 }
2011 
getStreamId(const QString & path)2012 static int getStreamId (const QString &path) {
2013     int p = path.lastIndexOf (QChar ('_'));
2014     if (p < 0) {
2015         kError() << "wrong object path " << path << endl;
2016         return -1;
2017     }
2018     bool ok;
2019     qint32 sid = path.mid (p+1).toInt (&ok);
2020     if (!ok) {
2021         kError() << "wrong object path suffix " << path.mid (p+1) << endl;
2022         return -1;
2023     }
2024     return sid;
2025 }
2026 
request_stream(const QString & path,const QString & url,const QString & target,const QByteArray & post)2027 KDE_NO_EXPORT void NpPlayer::request_stream (const QString &path, const QString &url, const QString &target, const QByteArray &post) {
2028     QString uri (url);
2029     kDebug () << "NpPlayer::request " << path << " '" << url << "' " << " tg:" << target << "post" << post.size ();
2030     bool js = url.startsWith ("javascript:");
2031     if (!js) {
2032         QString base = process_info->manager->player ()->docBase ().url ();
2033         uri = KUrl (base.isEmpty () ? m_url : base, url).url ();
2034     }
2035     kDebug () << "NpPlayer::request " << path << " '" << uri << "'" << m_url << "->" << url;
2036     qint32 sid = getStreamId (path);
2037     if ((int)sid >= 0) {
2038         if (!target.isEmpty ()) {
2039             kDebug () << "new page request " << target;
2040             if (js) {
2041                 QString result = evaluate (url.mid (11), false);
2042                 kDebug() << "result is " << result;
2043                 if (result == "undefined")
2044                     uri = QString ();
2045                 else
2046                     uri = KUrl (m_url, result).url (); // probably wrong ..
2047             }
2048             KUrl kurl(uri);
2049             if (kurl.isValid ())
2050                 process_info->manager->player ()->openUrl (kurl, target, QString ());
2051             sendFinish (sid, 0, NpStream::BecauseDone);
2052         } else {
2053             NpStream * ns = new NpStream (this, sid, uri, post);
2054             connect (ns, SIGNAL (stateChanged ()), this, SLOT (streamStateChanged ()));
2055             streams[sid] = ns;
2056             if (url != uri)
2057                 streamRedirected (sid, uri);
2058             if (!write_in_progress)
2059                 processStreams ();
2060         }
2061     }
2062 }
2063 
evaluate(const QString & script,bool store)2064 KDE_NO_EXPORT QString NpPlayer::evaluate (const QString &script, bool store) {
2065     QString result ("undefined");
2066     emit evaluate (script, store, result);
2067     //kDebug () << "evaluate " << script << " => " << result;
2068     return result;
2069 }
2070 
dimension(int w,int h)2071 KDE_NO_EXPORT void NpPlayer::dimension (int w, int h) {
2072     source ()->setAspect (mrl (), 1.0 * w/ h);
2073 }
2074 
destroyStream(uint32_t sid)2075 KDE_NO_EXPORT void NpPlayer::destroyStream (uint32_t sid) {
2076     if (streams.contains (sid)) {
2077         NpStream *ns = streams[sid];
2078         ns->close ();
2079         if (!write_in_progress)
2080             processStreams ();
2081     } else {
2082         kWarning () << "Object " << sid << " not found";
2083     }
2084     if (!sid)
2085         emit loaded ();
2086 }
2087 
2088 KDE_NO_EXPORT
sendFinish(quint32 sid,quint32 bytes,NpStream::Reason because)2089 void NpPlayer::sendFinish (quint32 sid, quint32 bytes, NpStream::Reason because) {
2090     kDebug() << "NpPlayer::sendFinish " << sid << " bytes:" << bytes;
2091     if (running ()) {
2092         uint32_t reason = (int) because;
2093         QString objpath = QString ("/stream_%1").arg (sid);
2094         QDBusMessage msg = QDBusMessage::createMethodCall (
2095                 remote_service, objpath, "org.kde.kmplayer.backend", "eof");
2096         msg << bytes << reason;
2097         msg.setDelayedReply (false);
2098         QDBusConnection::sessionBus().send (msg);
2099     }
2100     if (!sid)
2101         emit loaded ();
2102 }
2103 
terminateJobs()2104 KDE_NO_EXPORT void NpPlayer::terminateJobs () {
2105     Process::terminateJobs ();
2106     const StreamMap::iterator e = streams.end ();
2107     for (StreamMap::iterator i = streams.begin (); i != e; ++i)
2108         delete i.value ();
2109     streams.clear ();
2110 }
2111 
stop()2112 KDE_NO_EXPORT void NpPlayer::stop () {
2113     terminateJobs ();
2114     if (!running ())
2115         return;
2116     kDebug () << "NpPlayer::stop ";
2117     QDBusMessage msg = QDBusMessage::createMethodCall (
2118             remote_service, "/plugin", "org.kde.kmplayer.backend", "quit");
2119     msg.setDelayedReply (false);
2120     QDBusConnection::sessionBus().send (msg);
2121 }
2122 
quit()2123 KDE_NO_EXPORT void NpPlayer::quit () {
2124     if (running () && !m_process->waitForFinished (2000))
2125         Process::quit ();
2126 }
2127 
processOutput()2128 KDE_NO_EXPORT void NpPlayer::processOutput () {
2129     if (!remote_service.isEmpty ())
2130         outputToView (view (), m_process->readAllStandardOutput ());
2131     outputToView (view (), m_process->readAllStandardError ());
2132 }
2133 
processStopped(int,QProcess::ExitStatus)2134 KDE_NO_EXPORT void NpPlayer::processStopped (int, QProcess::ExitStatus) {
2135     terminateJobs ();
2136     if (m_source)
2137         m_source->document ()->message (MsgInfoString, NULL);
2138     setState (IProcess::NotRunning);
2139 }
2140 
streamStateChanged()2141 KDE_NO_EXPORT void NpPlayer::streamStateChanged () {
2142     setState (IProcess::Playing); // hmm, this doesn't really fit in current states
2143     if (!write_in_progress)
2144         processStreams ();
2145 }
2146 
streamRedirected(uint32_t sid,const QUrl & u)2147 KDE_NO_EXPORT void NpPlayer::streamRedirected(uint32_t sid, const QUrl& u) {
2148     if (running ()) {
2149         kDebug() << "redirected " << sid << " to " << u.url();
2150         QString objpath = QString ("/stream_%1").arg (sid);
2151         QDBusMessage msg = QDBusMessage::createMethodCall (
2152                 remote_service, objpath, "org.kde.kmplayer.backend", "redirected");
2153         msg << u.url ();
2154         msg.setDelayedReply (false);
2155         QDBusConnection::sessionBus().send (msg);
2156     }
2157 }
2158 
2159 KDE_NO_EXPORT
requestGet(const uint32_t id,const QString & prop,QString * res)2160 void NpPlayer::requestGet (const uint32_t id, const QString &prop, QString *res) {
2161     if (!remote_service.isEmpty ()) {
2162         QDBusMessage msg = QDBusMessage::createMethodCall (
2163                 remote_service, "/plugin", "org.kde.kmplayer.backend", "get");
2164         msg << id << prop;
2165         QDBusMessage rmsg = QDBusConnection::sessionBus().call (msg, QDBus::BlockWithGui);
2166         if (rmsg.type () == QDBusMessage::ReplyMessage) {
2167             //kDebug() << "get " << prop << rmsg.arguments ().size ();
2168             if (rmsg.arguments ().size ()) {
2169                 QString s = rmsg.arguments ().first ().toString ();
2170                 if (s != "error")
2171                     *res = s;
2172             }
2173         } else {
2174             kError() << "get" << prop << rmsg.type () << rmsg.errorMessage ();
2175         }
2176     }
2177 }
2178 
requestCall(const uint32_t id,const QString & func,const QStringList & args,QString * res)2179 KDE_NO_EXPORT void NpPlayer::requestCall (const uint32_t id, const QString &func,
2180         const QStringList &args, QString *res) {
2181     QDBusMessage msg = QDBusMessage::createMethodCall (
2182             remote_service, "/plugin", "org.kde.kmplayer.backend", "call");
2183     msg << id << func << args;
2184     QDBusMessage rmsg = QDBusConnection::sessionBus().call (msg, QDBus::BlockWithGui);
2185     //kDebug() << "call " << func << rmsg.arguments ().size ();
2186     if (rmsg.arguments ().size ()) {
2187         QString s = rmsg.arguments ().first ().toString ();
2188         if (s != "error")
2189             *res = s;
2190     }
2191 }
2192 
processStreams()2193 KDE_NO_EXPORT void NpPlayer::processStreams () {
2194     NpStream *stream = 0L;
2195     qint32 stream_id;
2196     timeval tv = { 0x7fffffff, 0 };
2197     const StreamMap::iterator e = streams.end ();
2198     int active_count = 0;
2199 
2200     if (in_process_stream || write_in_progress) {
2201         kDebug() << "wrong call" << kBacktrace();
2202         return;
2203     }
2204     in_process_stream = true;
2205 
2206     //kDebug() << "NpPlayer::processStreams " << streams.size ();
2207     for (StreamMap::iterator i = streams.begin (); i != e;) {
2208         NpStream *ns = i.value ();
2209         if (ns->job) {
2210             active_count++;
2211         } else if (active_count < 5 &&
2212                 ns->finish_reason == NpStream::NoReason) {
2213             write_in_progress = true; // javascript: urls emit stateChange
2214             ns->open ();
2215             write_in_progress = false;
2216             if (ns->job) {
2217                 connect(ns, SIGNAL(redirected(uint32_t, const QUrl&)),
2218                         this, SLOT(streamRedirected(uint32_t, const QUrl&)));
2219                 active_count++;
2220             }
2221         }
2222         if (ns->finish_reason == NpStream::BecauseStopped ||
2223                 ns->finish_reason == NpStream::BecauseError ||
2224                 (ns->finish_reason == NpStream::BecauseDone &&
2225                  ns->pending_buf.size () == 0)) {
2226             sendFinish (i.key(), ns->bytes, ns->finish_reason);
2227             i = streams.erase (i);
2228             delete ns;
2229         } else {
2230             if (ns->pending_buf.size () > 0 &&
2231                     (ns->data_arrival.tv_sec < tv.tv_sec ||
2232                      (ns->data_arrival.tv_sec == tv.tv_sec &&
2233                       ns->data_arrival.tv_usec < tv.tv_usec))) {
2234                 tv = ns->data_arrival;
2235                 stream = ns;
2236                 stream_id = i.key();
2237             }
2238             ++i;
2239         }
2240     }
2241     //kDebug() << "NpPlayer::processStreams " << stream;
2242     if (stream) {
2243         if (stream->finish_reason != NpStream::BecauseStopped &&
2244                 stream->finish_reason != NpStream::BecauseError &&
2245                 !stream->bytes &&
2246                 (!stream->mimetype.isEmpty() || stream->content_length)) {
2247             QString objpath = QString ("/stream_%1").arg (stream->stream_id);
2248             QDBusMessage msg = QDBusMessage::createMethodCall (
2249                     remote_service, objpath, "org.kde.kmplayer.backend", "streamInfo");
2250             msg << stream->mimetype
2251                 << stream->content_length
2252                 << stream->http_headers;
2253             msg.setDelayedReply (false);
2254             QDBusConnection::sessionBus().send (msg);
2255         }
2256         const int header_len = 2 * sizeof (qint32);
2257         qint32 chunk = stream->pending_buf.size ();
2258         send_buf.resize (chunk + header_len);
2259         memcpy (send_buf.data (), &stream_id, sizeof (qint32));
2260         memcpy (send_buf.data() + sizeof (qint32), &chunk, sizeof (qint32));
2261         memcpy (send_buf.data ()+header_len,
2262                 stream->pending_buf.constData (), chunk);
2263         stream->pending_buf = QByteArray ();
2264         /*fprintf (stderr, " => %d %d\n", (long)stream_id, chunk);*/
2265         stream->bytes += chunk;
2266         write_in_progress = true;
2267         m_process->write (send_buf);
2268         if (stream->finish_reason == NpStream::NoReason)
2269             stream->job->resume ();
2270     }
2271     in_process_stream = false;
2272 }
2273 
wroteStdin(qint64)2274 KDE_NO_EXPORT void NpPlayer::wroteStdin (qint64) {
2275     if (!m_process->bytesToWrite ()) {
2276         write_in_progress = false;
2277         if (running ())
2278             processStreams ();
2279     }
2280 }
2281 
cookie(const QString & url)2282 QString NpPlayer::cookie (const QString &url)
2283 {
2284     QString s;
2285     View *v = view ();
2286     if (v) {
2287         KIO::Integration::CookieJar jar (v);
2288         jar.setWindowId (v->topLevelWidget()->winId ());
2289         QList<QNetworkCookie> c = jar.cookiesForUrl (url);
2290         QList<QNetworkCookie>::const_iterator e = c.end ();
2291         for (QList<QNetworkCookie>::const_iterator i = c.begin (); i != e; ++i)
2292             s += (s.isEmpty() ? "" : ";") + QString::fromUtf8 ((*i).toRawForm());
2293     }
2294     return s;
2295 }
2296 
2297 #else
2298 
NpStream(NpPlayer * p,uint32_t sid,const QString & u,const QByteArray &)2299 KDE_NO_CDTOR_EXPORT NpStream::NpStream (NpPlayer *p, uint32_t sid, const QString &u, const QByteArray &/*ps*/)
2300     : QObject (p) {}
2301 
~NpStream()2302 KDE_NO_CDTOR_EXPORT NpStream::~NpStream () {}
slotResult(KJob *)2303 void NpStream::slotResult (KJob*) {}
slotData(KIO::Job *,const QByteArray &)2304 void NpStream::slotData (KIO::Job*, const QByteArray&) {}
redirection(KIO::Job *,const QUrl &)2305 void NpStream::redirection(KIO::Job*, const QUrl&) {}
slotMimetype(KIO::Job *,const QString &)2306 void NpStream::slotMimetype (KIO::Job *, const QString &) {}
slotTotalSize(KJob *,KIO::filesize_t)2307 void NpStream::slotTotalSize (KJob *, KIO::filesize_t) {}
2308 
2309 KDE_NO_CDTOR_EXPORT
NpPlayer(QObject * parent,ProcessInfo * pinfo,Settings * settings)2310 NpPlayer::NpPlayer (QObject *parent, ProcessInfo *pinfo, Settings *settings)
2311  : Process (parent, pinfo, settings) {}
~NpPlayer()2312 KDE_NO_CDTOR_EXPORT NpPlayer::~NpPlayer () {}
init()2313 KDE_NO_EXPORT void NpPlayer::init () {}
deMediafiedPlay()2314 KDE_NO_EXPORT bool NpPlayer::deMediafiedPlay () { return false; }
initProcess()2315 KDE_NO_EXPORT void NpPlayer::initProcess () {}
stop()2316 KDE_NO_EXPORT void NpPlayer::stop () {}
quit()2317 KDE_NO_EXPORT void NpPlayer::quit () { }
ready()2318 KDE_NO_EXPORT bool NpPlayer::ready () { return false; }
requestGet(const uint32_t,const QString &,QString *)2319 KDE_NO_EXPORT void NpPlayer::requestGet (const uint32_t, const QString &, QString *) {}
requestCall(const uint32_t,const QString &,const QStringList &,QString *)2320 KDE_NO_EXPORT void NpPlayer::requestCall (const uint32_t, const QString &, const QStringList &, QString *) {}
processOutput()2321 KDE_NO_EXPORT void NpPlayer::processOutput () {}
processStopped(int,QProcess::ExitStatus)2322 KDE_NO_EXPORT void NpPlayer::processStopped (int, QProcess::ExitStatus) {}
wroteStdin(qint64)2323 KDE_NO_EXPORT void NpPlayer::wroteStdin (qint64) {}
streamStateChanged()2324 KDE_NO_EXPORT void NpPlayer::streamStateChanged () {}
streamRedirected(uint32_t,const QUrl &)2325 KDE_NO_EXPORT void NpPlayer::streamRedirected(uint32_t, const QUrl&) {}
terminateJobs()2326 KDE_NO_EXPORT void NpPlayer::terminateJobs () {}
2327 
2328 #endif
2329 
2330 #include "kmplayerprocess.moc"
2331