File indexing completed on 2024-04-28 12:39:39

0001 /*
0002     This file is part of the KMPlayer application
0003     SPDX-FileCopyrightText: 2004 Koos Vriezen <koos.vriezen@xs4all.nl>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include <cmath>
0009 #include <unistd.h>
0010 
0011 #include <QLayout>
0012 #include <QLabel>
0013 #include <QMap>
0014 #include <QTimer>
0015 #include <QPushButton>
0016 #include <Q3ButtonGroup>
0017 #include <QCheckBox>
0018 #include <QTable>
0019 #include <QStringList>
0020 #include <QComboBox>
0021 #include <QLineEdit>
0022 #include <QGroupBox>
0023 #include <QWhatsThis>
0024 #include <QTabWidget>
0025 #include <QRadioButton>
0026 #include <QMessageBox>
0027 #include <QSocket>
0028 #include <QEventLoop>
0029 
0030 #include <KLocalizedString>
0031 #include <KMessageBox>
0032 #include <KLineEdit>
0033 #include <KUrlRequester>
0034 #include <KComboBox>
0035 #include <kstatusbar.h>
0036 #include <kprocess.h>
0037 #include <KConfig>
0038 #include <kaction.h>
0039 #include <KIconLoader>
0040 #include <klistview.h>
0041 #include <kinputdialog.h>
0042 
0043 #include "kmplayerapp_log.h"
0044 #include "kmplayer_backend_stub.h"
0045 #include "kmplayer_callback.h"
0046 #include "kmplayerpartbase.h"
0047 #include "kmplayercontrolpanel.h"
0048 #include "kmplayerconfig.h"
0049 #include "playlistview.h"
0050 #include "viewarea.h"
0051 #include "kmplayervdr.h"
0052 #include "kmplayer.h"
0053 
0054 using namespace KMPlayer;
0055 
0056 static const char * strVDR = "VDR";
0057 static const char * strVDRPort = "Port";
0058 static const char * strXVPort = "XV Port";
0059 static const char * strXVEncoding = "XV Encoding";
0060 static const char * strXVScale = "XV Scale";
0061 
0062 KMPlayerPrefSourcePageVDR::KMPlayerPrefSourcePageVDR (QWidget * parent, KMPlayer::PartBase * player)
0063  : QFrame (parent), m_player (player) {
0064     //KUrlRequester * v4ldevice;
0065     QVBoxLayout *layout = new QVBoxLayout (this, 5, 2);
0066     QGridLayout *gridlayout = new QGridLayout (1, 2);
0067     xv_port = new KListView (this);
0068     xv_port->addColumn (QString());
0069     xv_port->header()->hide ();
0070     xv_port->setTreeStepSize (15);
0071     //xv_port->setRootIsDecorated (true);
0072     //xv_port->setSorting (-1);
0073     Q3ListViewItem * vitem = new Q3ListViewItem (xv_port, i18n ("XVideo port"));
0074     vitem->setOpen (true);
0075     QWhatsThis::add (xv_port, i18n ("Port base of the X Video extension.\nIf left to default (0), the first available port will be used. However if you have multiple XVideo instances, you might have to provide the port to use here.\nSee the output from 'xvinfo' for more information"));
0076     QLabel * label = new QLabel (i18n ("Communication port:"), this);
0077     gridlayout->addWidget (label, 0, 0);
0078     tcp_port = new QLineEdit ("", this);
0079     QWhatsThis::add (tcp_port, i18n ("Communication port with VDR. Default is port 2001.\nIf you use another port, with the '-p' option of 'vdr', you must set it here too."));
0080     gridlayout->addWidget (tcp_port, 0, 1);
0081     layout->addWidget (xv_port);
0082     layout->addLayout (gridlayout);
0083     scale = new Q3ButtonGroup (2, Qt::Vertical, i18n ("Scale"), this);
0084     new QRadioButton (i18n ("4:3"), scale);
0085     new QRadioButton (i18n ("16:9"), scale);
0086     QWhatsThis::add (scale, i18n ("Aspects to use when viewing VDR"));
0087     scale->setButton (0);
0088     layout->addWidget (scale);
0089     layout->addItem (new QSpacerItem (5, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
0090 }
0091 
0092 KMPlayerPrefSourcePageVDR::~KMPlayerPrefSourcePageVDR () {}
0093 
0094 void KMPlayerPrefSourcePageVDR::showEvent (QShowEvent *) {
0095     XvProcessInfo *pi = static_cast<XvProcessInfo *>(m_player->mediaManager()->
0096             processInfos()["xvideo"]);
0097     if (!pi->config_doc)
0098         pi->getConfigData ();
0099 }
0100 //-----------------------------------------------------------------------------
0101 
0102 static const char * cmd_chan_query = "CHAN\n";
0103 static const char * cmd_list_channels = "LSTC\n";
0104 static const char * cmd_volume_query = "VOLU\n";
0105 
0106 class VDRCommand {
0107 public:
0108     VDRCommand (const char * c, VDRCommand * n=0L)
0109         : command (strdup (c)), next (n) {}
0110     ~VDRCommand () { free (command); }
0111     char * command;
0112     VDRCommand * next;
0113 };
0114 
0115 //-----------------------------------------------------------------------------
0116 
0117 KMPlayerVDRSource::KMPlayerVDRSource (KMPlayerApp * app)
0118  : KMPlayer::Source (QString ("VDR"), app->player (), "vdrsource"),
0119    m_app (app),
0120    m_configpage (0),
0121    m_socket (new QSocket (this)), 
0122    commands (0L),
0123    channel_timer (0),
0124    timeout_timer (0),
0125    finish_timer (0),
0126    tcp_port (0),
0127    m_stored_volume (0) {
0128     memset (m_actions, 0, sizeof (KAction *) * int (act_last));
0129     m_player->settings ()->addPage (this);
0130     connect (m_socket, SIGNAL (connectionClosed()), this, SLOT(disconnected()));
0131     connect (m_socket, SIGNAL (connected ()), this, SLOT (connected ()));
0132     connect (m_socket, SIGNAL (readyRead ()), this, SLOT (readyRead ()));
0133     connect (m_socket, SIGNAL (error (int)), this, SLOT (socketError (int)));
0134 }
0135 
0136 KMPlayerVDRSource::~KMPlayerVDRSource () {}
0137 
0138 void KMPlayerVDRSource::waitForConnectionClose () {
0139     if (timeout_timer) {
0140         finish_timer = startTimer (500);
0141         kdDebug () << "VDR connection not yet closed" << endl;
0142         QApplication::eventLoop ()->enterLoop ();
0143         kdDebug () << "VDR connection:" << (m_socket->state () == QSocket::Connected) << endl;
0144         timeout_timer = 0;
0145     }
0146 }
0147 
0148 bool KMPlayerVDRSource::hasLength () {
0149     return false;
0150 }
0151 
0152 bool KMPlayerVDRSource::isSeekable () {
0153     return true;
0154 }
0155 
0156 QString KMPlayerVDRSource::prettyName () {
0157     return i18n ("VDR");
0158 }
0159 
0160 void KMPlayerVDRSource::activate () {
0161     last_channel = 0;
0162     connect (this, SIGNAL (startPlaying ()), this, SLOT (processStarted()));
0163     connect (this, SIGNAL (stopPlaying ()), this, SLOT (processStopped ()));
0164     KMPlayer::ControlPanel * panel = m_app->view()->controlPanel ();
0165     panel->button (KMPlayer::ControlPanel::button_red)->show ();
0166     panel->button (KMPlayer::ControlPanel::button_green)->show ();
0167     panel->button (KMPlayer::ControlPanel::button_yellow)->show ();
0168     panel->button (KMPlayer::ControlPanel::button_blue)->show ();
0169     panel->button (KMPlayer::ControlPanel::button_pause)->hide ();
0170     panel->button (KMPlayer::ControlPanel::button_record)->hide ();
0171     connect (panel->volumeBar (), SIGNAL (volumeChanged (int)), this, SLOT (volumeChanged (int)));
0172     connect (panel->button (KMPlayer::ControlPanel::button_red), SIGNAL (clicked ()), this, SLOT (keyRed ()));
0173     connect (panel->button (KMPlayer::ControlPanel::button_green), SIGNAL (clicked ()), this, SLOT (keyGreen ()));
0174     connect (panel->button (KMPlayer::ControlPanel::button_yellow), SIGNAL (clicked ()), this, SLOT (keyYellow ()));
0175     connect (panel->button (KMPlayer::ControlPanel::button_blue), SIGNAL (clicked ()), this, SLOT (keyBlue ()));
0176     setAspect (m_document, scale ? 16.0/9 : 1.33);
0177     if (!m_url.scheme().compare ("kmplayer"))
0178         m_request_jump = QUrl::fromPercentEncoding(m_url.path().latin1()).mid (1);
0179     setUrl (QString ("vdr://localhost:%1").arg (tcp_port));
0180     QTimer::singleShot (0, m_player, SLOT (play ()));
0181 }
0182 
0183 void KMPlayerVDRSource::deactivate () {
0184     disconnect (m_socket, SIGNAL (error (int)), this, SLOT (socketError (int)));
0185     if (m_player->view ()) {
0186         disconnect (this, SIGNAL(startPlaying()), this, SLOT(processStarted()));
0187         disconnect (this, SIGNAL (stopPlaying()), this, SLOT(processStopped()));
0188         KMPlayer::ControlPanel * panel = m_app->view()->controlPanel ();
0189         disconnect (panel->volumeBar (), SIGNAL (volumeChanged (int)), this, SLOT (volumeChanged (int)));
0190         disconnect (panel->button (KMPlayer::ControlPanel::button_red), SIGNAL (clicked ()), this, SLOT (keyRed ()));
0191         disconnect (panel->button (KMPlayer::ControlPanel::button_green), SIGNAL (clicked ()), this, SLOT (keyGreen ()));
0192         disconnect (panel->button (KMPlayer::ControlPanel::button_yellow), SIGNAL (clicked ()), this, SLOT (keyYellow ()));
0193         disconnect (panel->button (KMPlayer::ControlPanel::button_blue), SIGNAL (clicked ()), this, SLOT (keyBlue ()));
0194     }
0195     processStopped ();
0196     m_request_jump.truncate (0);
0197 }
0198 
0199 void KMPlayerVDRSource::processStopped () {
0200     if (m_socket->state () == QSocket::Connected) {
0201         queueCommand (QString ("VOLU %1\n").arg (m_stored_volume).ascii ());
0202         queueCommand ("QUIT\n");
0203     }
0204 }
0205 
0206 void KMPlayerVDRSource::processStarted () {
0207     m_socket->connectToHost ("127.0.0.1", tcp_port);
0208     commands = new VDRCommand ("connect", commands);
0209 }
0210 
0211 #define DEF_ACT(i,text,pix,scut,slot,name) \
0212     m_actions [i] = new KAction (text, QString (pix), KShortcut (scut), this, slot, m_app->actionCollection (), name); \
0213     m_fullscreen_actions [i] = new KAction (text, KShortcut (scut), this, slot, m_app->view ()->viewArea ()->actionCollection (), name)
0214 
0215 void KMPlayerVDRSource::connected () {
0216     queueCommand (cmd_list_channels);
0217     queueCommand (cmd_volume_query);
0218     killTimer (channel_timer);
0219     channel_timer = startTimer (3000);
0220     KAction * action = m_app->actionCollection ()->action ("vdr_connect");
0221     action->setIcon (QString ("network-disconnect"));
0222     action->setText (i18n ("Dis&connect"));
0223     DEF_ACT (act_up, i18n ("VDR Key Up"), "go-up", , SLOT (keyUp ()), "vdr_key_up");
0224     DEF_ACT (act_down, i18n ("VDR Key Down"), "go-down", , SLOT (keyDown ()), "vdr_key_down");
0225     DEF_ACT (act_back, i18n ("VDR Key Back"), "go-previous", , SLOT (keyBack ()), "vdr_key_back");
0226     DEF_ACT (act_ok, i18n ("VDR Key Ok"), "dialog-ok", , SLOT (keyOk ()), "vdr_key_ok");
0227     DEF_ACT (act_setup, i18n ("VDR Key Setup"), "configure", , SLOT (keySetup ()), "vdr_key_setup");
0228     DEF_ACT (act_channels, i18n ("VDR Key Channels"), "view-media-playlist", , SLOT (keyChannels ()), "vdr_key_channels");
0229     DEF_ACT (act_menu, i18n ("VDR Key Menu"), "show-menu", , SLOT (keyMenu ()), "vdr_key_menu");
0230     DEF_ACT (act_red, i18n ("VDR Key Red"), "red", , SLOT (keyRed ()), "vdr_key_red");
0231     DEF_ACT (act_green, i18n ("VDR Key Green"), "green", , SLOT (keyGreen ()), "vdr_key_green");
0232     DEF_ACT (act_yellow, i18n ("VDR Key Yellow"), "yellow", , SLOT (keyYellow ()), "vdr_key_yellow");
0233     DEF_ACT (act_blue, i18n ("VDR Key Blue"), "blue", , SLOT (keyBlue ()), "vdr_key_blue");
0234     DEF_ACT (act_custom, "VDR Custom Command", "system-run", , SLOT (customCmd ()), "vdr_key_custom");
0235     m_app->initMenu (); // update menu and toolbar
0236     DEF_ACT (act_0, i18n ("VDR Key 0"), "0", Qt::Key_0, SLOT (key0 ()), "vdr_key_0");
0237     DEF_ACT (act_1, i18n ("VDR Key 1"), "1", Qt::Key_1, SLOT (key1 ()), "vdr_key_1");
0238     DEF_ACT (act_2, i18n ("VDR Key 2"), "2", Qt::Key_2, SLOT (key2 ()), "vdr_key_2");
0239     DEF_ACT (act_3, i18n ("VDR Key 3"), "3", Qt::Key_3, SLOT (key3 ()), "vdr_key_3");
0240     DEF_ACT (act_4, i18n ("VDR Key 4"), "4", Qt::Key_4, SLOT (key4 ()), "vdr_key_4");
0241     DEF_ACT (act_5, i18n ("VDR Key 5"), "5", Qt::Key_5, SLOT (key5 ()), "vdr_key_5");
0242     DEF_ACT (act_6, i18n ("VDR Key 6"), "6", Qt::Key_6, SLOT (key6 ()), "vdr_key_6");
0243     DEF_ACT (act_7, i18n ("VDR Key 7"), "7", Qt::Key_7, SLOT (key7 ()), "vdr_key_7");
0244     DEF_ACT (act_8, i18n ("VDR Key 8"), "8", Qt::Key_8, SLOT (key8 ()), "vdr_key_8");
0245     DEF_ACT (act_9, i18n ("VDR Key 9"), "9", Qt::Key_9, SLOT (key9 ()), "vdr_key_9");
0246     //KMPlayer::ViewLayer * layer = m_app->view ()->viewArea ();
0247     for (int i = 0; i < int (act_last); ++i)
0248         // somehow, the configured shortcuts only show up after createGUI() call
0249         m_fullscreen_actions [i]->setShortcut (m_actions [i]->shortcut ());
0250     //    m_fullscreen_actions[i]->plug (layer);
0251 }
0252 
0253 #undef DEF_ACT
0254 
0255 void KMPlayerVDRSource::disconnected () {
0256     kdDebug() << "disconnected " << commands << endl;
0257     if (finish_timer) {
0258         deleteCommands ();
0259         return;
0260     }
0261     setUrl (QString ("vdr://localhost:%1").arg (tcp_port));
0262     if (channel_timer && m_player->source () == this)
0263         m_player->stop ();
0264     deleteCommands ();
0265     KAction * action = m_app->actionCollection ()->action ("vdr_connect");
0266     action->setIcon (QString ("network-connect"));
0267     action->setText (i18n ("&Connect"));
0268     m_app->guiFactory ()->removeClient (m_app);// crash w/ m_actions[i]->unplugAll (); in for loop below
0269     for (int i = 0; i < int (act_last); ++i)
0270         if (m_player->view () && m_actions[i]) {
0271             m_fullscreen_actions[i]->unplug (m_app->view()->viewArea());
0272             delete m_actions[i];
0273             delete m_fullscreen_actions[i];
0274         }
0275     m_app->initMenu ();
0276 }
0277 
0278 void KMPlayerVDRSource::toggleConnected () {
0279     if (m_socket->state () == QSocket::Connected) {
0280         queueCommand ("QUIT\n");
0281         killTimer (channel_timer);
0282         channel_timer = 0;
0283     } else {
0284         m_socket->connectToHost ("127.0.0.1", tcp_port);
0285         commands = new VDRCommand ("connect", commands);
0286     }
0287 }
0288 
0289 void KMPlayerVDRSource::volumeChanged (int val) {
0290     queueCommand (QString ("VOLU %1\n").arg (int (sqrt (255 * 255 * val / 100))).ascii ());
0291 }
0292 
0293 static struct ReadBuf {
0294     char * buf;
0295     int length;
0296     ReadBuf () : buf (0L), length (0) {}
0297     ~ReadBuf () {
0298         clear ();
0299     }
0300     void operator += (const char * s) {
0301         int l = strlen (s);
0302         char * b = new char [length + l + 1];
0303         if (length)
0304             strcpy (b, buf);
0305         strcpy (b + length, s);
0306         length += l;
0307         delete buf;
0308         buf = b;
0309     }
0310     QCString mid (int p) {
0311         return QCString (buf + p);
0312     }
0313     QCString left (int p) {
0314         return QCString (buf, p);
0315     }
0316     QCString getReadLine ();
0317     void clear () {
0318         delete [] buf;
0319         buf = 0;
0320         length = 0;
0321     }
0322 } readbuf;
0323 
0324 QCString ReadBuf::getReadLine () {
0325     QCString out;
0326     if (!length)
0327         return out;
0328     int p = strcspn (buf, "\r\n");
0329     if (p < length) {
0330         int skip = strspn (buf + p, "\r\n");
0331         out = left (p+1);
0332         int nl = length - p - skip;
0333         memmove (buf, buf + p + skip, nl + 1);
0334         length = nl;
0335     }
0336     return out;
0337 }
0338 
0339 void KMPlayerVDRSource::readyRead () {
0340     KMPlayer::View * v = finish_timer ? 0L : static_cast <KMPlayer::View *> (m_player->view ());
0341     long nr = m_socket->bytesAvailable();
0342     char * data = new char [nr + 1];
0343     m_socket->readBlock (data, nr);
0344     data [nr] = 0;
0345     readbuf += data;
0346     QCString line = readbuf.getReadLine ();
0347     if (commands) {
0348         bool cmd_done = false;
0349         while (!line.isEmpty ()) {
0350             bool toconsole = true;
0351             cmd_done = (line.length () > 3 && line[3] == ' '); // from svdrpsend.pl
0352             // kdDebug () << "readyRead " << cmd_done << " " << commands->command << endl;
0353             if (!strcmp (commands->command, cmd_list_channels) && m_document) {
0354                 int p = line.find (';');
0355                 int q = line.find (':');
0356                 if (q > 0 && (p < 0 || q < p))
0357                     p = q;
0358                 if (p > 0)
0359                     line.truncate (p);
0360                 QString channel_name = line.mid (4);
0361                 m_document->appendChild (new KMPlayer::GenericMrl (m_document, QString ("kmplayer://vdrsource/%1").arg(channel_name), channel_name));
0362                 if (cmd_done) {
0363                     m_player->updateTree ();
0364                     if (!m_request_jump.isEmpty ()) {
0365                         jump (m_request_jump);
0366                         m_request_jump.truncate (0);
0367                     }
0368                 }
0369                 toconsole = false;
0370             } else if (!strcmp (commands->command, cmd_chan_query)) {
0371                 if (v && line.length () > 4) {
0372                     QString ch = line.mid (4);
0373                     setTitle (ch);
0374                     KMPlayer::PlayListItem * lvi = static_cast <KMPlayer::PlayListItem *> (v->playList ()->findItem (ch, 0));
0375                     if (lvi && lvi->node != m_last_channel) {
0376                         KMPlayer::PlayListItem * si = static_cast <KMPlayer::PlayListItem *> (v->playList ()->selectedItem ());
0377                         bool jump_selection = (si && (si->node == m_document || si->node == m_last_channel));
0378                         if (m_last_channel)
0379                             m_last_channel->setState (KMPlayer::Node::state_finished);
0380                         m_last_channel = lvi->node;
0381                         if (m_last_channel)
0382                             m_last_channel->setState (KMPlayer::Node::state_began);
0383                         if (jump_selection) {
0384                             v->playList ()->setSelected (lvi, true);
0385                             v->playList ()->ensureItemVisible (lvi);
0386                         }
0387                         v->playList ()->triggerUpdate ();
0388                     }
0389                     //v->playList ()->selectItem (ch);
0390                     int c = strtol(ch.ascii(), 0L, 10);
0391                     if (c != last_channel) {
0392                         last_channel = c;
0393                         m_app->statusBar ()->changeItem (QString::number (c),
0394                                                          id_status_timer);
0395                     }
0396                 }
0397             } else if (cmd_done && !strcmp(commands->command,cmd_volume_query)){
0398                 int pos = line.lastIndexOf (QChar (' '));
0399                 if (pos > 0) {
0400                     QString vol = line.mid (pos + 1);
0401                     if (!vol.compare ("mute"))
0402                         m_stored_volume = 0;
0403                     else
0404                         m_stored_volume = vol.toInt ();
0405                     if (m_stored_volume == 0)
0406                         volumeChanged (m_app->view ()->controlPanel ()->volumeBar ()->value ());
0407                 }
0408             }
0409             if (v && toconsole)
0410                 v->addText (QString (line), true);
0411             line = readbuf.getReadLine ();
0412         }
0413         if (cmd_done) {
0414             VDRCommand * c = commands->next;
0415             delete commands;
0416             commands = c;
0417             if (commands)
0418                 sendCommand ();
0419             else {
0420                 killTimer (timeout_timer);
0421                 timeout_timer = 0;
0422             }
0423         }
0424     }
0425     delete [] data;
0426 }
0427 
0428 void KMPlayerVDRSource::socketError (int code) {
0429     if (code == QSocket::ErrHostNotFound) {
0430         KMessageBox::error (m_configpage, i18n ("Host not found"), i18n ("Error"));
0431     } else if (code == QSocket::ErrConnectionRefused) {
0432         KMessageBox::error (m_configpage, i18n ("Connection refused"), i18n ("Error"));
0433     }
0434 }
0435 
0436 void KMPlayerVDRSource::queueCommand (const char * cmd) {
0437     if (m_player->source () != this)
0438         return;
0439     if (!commands) {
0440         readbuf.clear ();
0441         commands = new VDRCommand (cmd);
0442         if (m_socket->state () == QSocket::Connected) {
0443             sendCommand ();
0444         } else {
0445             m_socket->connectToHost ("127.0.0.1", tcp_port);
0446             commands = new VDRCommand ("connect", commands);
0447         }
0448     } else {
0449         VDRCommand * c = commands;
0450         for (int i = 0; i < 10; ++i, c = c->next)
0451             if (!c->next) {
0452                 c->next = new VDRCommand (cmd);
0453                 break;
0454             }
0455     }
0456 }
0457 
0458 void KMPlayerVDRSource::queueCommand (const char * cmd, int t) {
0459     queueCommand (cmd);
0460     killTimer (channel_timer);
0461     channel_timer = startTimer (t);
0462 }
0463 
0464 void KMPlayerVDRSource::sendCommand () {
0465     //kdDebug () << "sendCommand " << commands->command << endl;
0466     m_socket->writeBlock (commands->command, strlen(commands->command));
0467     m_socket->flush ();
0468     killTimer (timeout_timer);
0469     timeout_timer = startTimer (30000);
0470 }
0471 
0472 void KMPlayerVDRSource::customCmd () {
0473     QString cmd = KInputDialog::getText (i18n ("Custom VDR command"), i18n ("You can pass commands to VDR.\nEnter 'HELP' to see a list of available commands.\nYou can see VDR response in the console window.\n\nVDR Command:"), QString(), 0, m_player->view ());
0474     if (!cmd.isEmpty ())
0475         queueCommand (QString (cmd + QChar ('\n')).local8Bit ());
0476 }
0477 
0478 void KMPlayerVDRSource::timerEvent (QTimerEvent * e) {
0479     if (e->timerId () == timeout_timer || e->timerId () == finish_timer) {
0480         deleteCommands ();
0481     } else if (e->timerId () == channel_timer) {
0482         queueCommand (cmd_chan_query);
0483         killTimer (channel_timer);
0484         channel_timer = startTimer (30000);
0485     }
0486 }
0487 
0488 void KMPlayerVDRSource::deleteCommands () {
0489     killTimer (timeout_timer);
0490     timeout_timer = 0;
0491     killTimer (channel_timer);
0492     channel_timer = 0;
0493     for (VDRCommand * c = commands; c; c = commands) {
0494         commands = commands->next;
0495         delete c;
0496     }
0497     readbuf.clear ();
0498     if (finish_timer) {
0499         killTimer (finish_timer);
0500         QApplication::eventLoop ()->exitLoop ();
0501     }
0502 }
0503 
0504 void KMPlayerVDRSource::play (KMPlayer::Mrl *mrl) {
0505     if (!mrl || !mrl->isPlayable ()) return;
0506     jump (mrl->pretty_name);
0507 }
0508 
0509 void KMPlayerVDRSource::jump (const QString & channel) {
0510     QCString c ("CHAN ");
0511     QCString ch = channel.local8Bit ();
0512     int p = ch.find (' ');
0513     if (p > 0)
0514         c += ch.left (p);
0515     else
0516         c += ch; // hope for the best ..
0517     c += '\n';
0518     queueCommand (c);
0519 }
0520 
0521 void KMPlayerVDRSource::forward () {
0522     queueCommand ("CHAN +\n", 1000);
0523 }
0524 
0525 void KMPlayerVDRSource::backward () {
0526     queueCommand ("CHAN -\n", 1000);
0527 }
0528 
0529 void KMPlayerVDRSource::keyUp () {
0530     queueCommand ("HITK UP\n", 1000);
0531 }
0532 
0533 void KMPlayerVDRSource::keyDown () {
0534     queueCommand ("HITK DOWN\n", 1000);
0535 }
0536 
0537 void KMPlayerVDRSource::keyBack () {
0538     queueCommand ("HITK BACK\n");
0539 }
0540 
0541 void KMPlayerVDRSource::keyOk () {
0542     queueCommand ("HITK OK\n");
0543 }
0544 
0545 void KMPlayerVDRSource::keySetup () {
0546     queueCommand ("HITK SETUP\n");
0547 }
0548 
0549 void KMPlayerVDRSource::keyChannels () {
0550     queueCommand ("HITK CHANNELS\n");
0551 }
0552 
0553 void KMPlayerVDRSource::keyMenu () {
0554     queueCommand ("HITK MENU\n");
0555 }
0556 
0557 void KMPlayerVDRSource::key0 () {
0558     queueCommand ("HITK 0\n", 2000);
0559 }
0560 
0561 void KMPlayerVDRSource::key1 () {
0562     queueCommand ("HITK 1\n", 2000);
0563 }
0564 
0565 void KMPlayerVDRSource::key2 () {
0566     queueCommand ("HITK 2\n", 2000);
0567 }
0568 
0569 void KMPlayerVDRSource::key3 () {
0570     queueCommand ("HITK 3\n", 2000);
0571 }
0572 
0573 void KMPlayerVDRSource::key4 () {
0574     queueCommand ("HITK 4\n", 2000);
0575 }
0576 
0577 void KMPlayerVDRSource::key5 () {
0578     queueCommand ("HITK 5\n", 2000);
0579 }
0580 
0581 void KMPlayerVDRSource::key6 () {
0582     queueCommand ("HITK 6\n", 2000);
0583 }
0584 
0585 void KMPlayerVDRSource::key7 () {
0586     queueCommand ("HITK 7\n", 2000);
0587 }
0588 
0589 void KMPlayerVDRSource::key8 () {
0590     queueCommand ("HITK 8\n", 2000);
0591 }
0592 
0593 void KMPlayerVDRSource::key9 () {
0594     queueCommand ("HITK 9\n", 2000);
0595 }
0596 
0597 void KMPlayerVDRSource::keyRed () {
0598     queueCommand ("HITK RED\n");
0599 }
0600 
0601 void KMPlayerVDRSource::keyGreen () {
0602     queueCommand ("HITK GREEN\n");
0603 }
0604 
0605 void KMPlayerVDRSource::keyYellow () {
0606     queueCommand ("HITK YELLOW\n");
0607 }
0608 
0609 void KMPlayerVDRSource::keyBlue () {
0610     queueCommand ("HITK BLUE\n");
0611 }
0612 
0613 void KMPlayerVDRSource::write (KConfig * m_config) {
0614     m_config->setGroup (strVDR);
0615     m_config->writeEntry (strVDRPort, tcp_port);
0616     m_config->writeEntry (strXVPort, m_xvport);
0617     m_config->writeEntry (strXVEncoding, m_xvencoding);
0618     m_config->writeEntry (strXVScale, scale);
0619 }
0620 
0621 void KMPlayerVDRSource::read (KConfig * m_config) {
0622     m_config->setGroup (strVDR);
0623     tcp_port = m_config->readNumEntry (strVDRPort, 2001);
0624     m_xvport = m_config->readNumEntry (strXVPort, 0);
0625     m_xvencoding = m_config->readNumEntry (strXVEncoding, 0);
0626     scale = m_config->readNumEntry (strXVScale, 0);
0627 }
0628 
0629 struct XVTreeItem : public Q3ListViewItem {
0630     XVTreeItem (Q3ListViewItem *parent, const QString & t, int p, int e)
0631         : Q3ListViewItem (parent, t), port (p), encoding (e) {}
0632     int port;
0633     int encoding;
0634 };
0635 
0636 void KMPlayerVDRSource::sync (bool fromUI) {
0637     XvProcessInfo *pi = static_cast<XvProcessInfo *>(m_player->mediaManager()->
0638             processInfos()["xvideo"]);
0639     if (fromUI) {
0640         tcp_port = m_configpage->tcp_port->text ().toInt ();
0641         scale = m_configpage->scale->id (m_configpage->scale->selected ());
0642         setAspect (m_document, scale ? 16.0/9 : 1.25);
0643         XVTreeItem * vitem = dynamic_cast <XVTreeItem *> (m_configpage->xv_port->selectedItem ());
0644         if (vitem) {
0645             m_xvport = vitem->port;
0646             m_xvencoding = vitem->encoding;
0647         }
0648     } else {
0649         m_configpage->tcp_port->setText (QString::number (tcp_port));
0650         m_configpage->scale->setButton (scale);
0651         Q3ListViewItem * vitem = m_configpage->xv_port->firstChild ();
0652         NodePtr configdoc = pi->config_doc;
0653         if (configdoc && configdoc->firstChild ()) {
0654             for (Q3ListViewItem *i=vitem->firstChild(); i; i=vitem->firstChild())
0655                 delete i;
0656             NodePtr node = configdoc->firstChild ();
0657             for (node = node->firstChild (); node; node = node->nextSibling()) {
0658                 if (!node->isElementNode ())
0659                     continue; // some text sneaked in ?
0660                 Element * elm = convertNode <Element> (node);
0661                 if (elm->getAttribute (KMPlayer::StringPool::attr_type) !=
0662                         QString ("tree"))
0663                     continue;
0664                 for (NodePtr n = elm->firstChild (); n; n = n->nextSibling ()) {
0665                     if (!n->isElementNode () || strcmp (n->nodeName (), "Port"))
0666                         continue;
0667                     Element * e = convertNode <Element> (n);
0668                     QString portatt = e->getAttribute (
0669                             KMPlayer::StringPool::attr_value);
0670                     int port;
0671                     Q3ListViewItem *pi = new Q3ListViewItem (vitem, i18n ("Port ") + portatt);
0672                     port = portatt.toInt ();
0673                     for (NodePtr in=e->firstChild(); in; in=in->nextSibling()) {
0674                         if (!in->isElementNode () ||
0675                                 strcmp (in->nodeName (), "Input"))
0676                             continue;
0677                         Element * i = convertNode <Element> (in);
0678                         QString inp = i->getAttribute (
0679                                 KMPlayer::StringPool::attr_name);
0680                         int enc = i->getAttribute (
0681                                 KMPlayer::StringPool::attr_value).toInt ();
0682                         Q3ListViewItem * ii = new XVTreeItem(pi, inp, port, enc);
0683                         if (m_xvport == port && enc == m_xvencoding) {
0684                             ii->setSelected (true);
0685                             m_configpage->xv_port->ensureItemVisible (ii);
0686                         }
0687                     }
0688                 }
0689             }
0690         } else { // wait for showEvent
0691             connect(pi, SIGNAL(configReceived()), this, SLOT(configReceived()));
0692         }
0693     }
0694 }
0695 
0696 void KMPlayerVDRSource::configReceived () {
0697     XvProcessInfo *pi = static_cast<XvProcessInfo *>(m_player->mediaManager()->
0698             processInfos()["xvideo"]);
0699     disconnect (pi, SIGNAL (configReceived()), this, SLOT (configReceived()));
0700     sync (false);
0701 }
0702 
0703 void KMPlayerVDRSource::prefLocation (QString & item, QString & icon, QString & tab) {
0704     item = i18n ("Source");
0705     icon = QString ("source");
0706     tab = i18n ("VDR");
0707 }
0708 
0709 QFrame * KMPlayerVDRSource::prefPage (QWidget * parent) {
0710     if (!m_configpage)
0711         m_configpage = new KMPlayerPrefSourcePageVDR (parent, m_player);
0712     return m_configpage;
0713 }
0714 
0715 void KMPlayerVDRSource::stateElementChanged (KMPlayer::Node *, KMPlayer::Node::State, KMPlayer::Node::State) {
0716 }
0717 
0718 //-----------------------------------------------------------------------------
0719 
0720 static const char * xv_supported [] = {
0721     "tvsource", "vdrsource", 0L
0722 };
0723 
0724 XvProcessInfo::XvProcessInfo (MediaManager *mgr)
0725  : CallbackProcessInfo ("xvideo", i18n ("X&Video"), xv_supported, mgr, NULL) {}
0726 
0727 IProcess *XvProcessInfo::create (PartBase *part, AudioVideoMedia *media) {
0728     XVideo *x = new XVideo (part, this, part->settings ());
0729     x->setSource (part->source ());
0730     x->media_object = media;
0731     part->processCreated (x);
0732     return x;
0733 }
0734 
0735 bool XvProcessInfo::startBackend () {
0736     if (m_process && m_process->isRunning ())
0737         return true;
0738     Settings *cfg = manager->player ()->settings();
0739 
0740     initProcess ();
0741 
0742     QString cmd  = QString ("kxvplayer -cb %1").arg (dcopName ());
0743     if (have_config == config_unknown || have_config == config_probe)
0744         cmd += QString (" -c");
0745     //if (m_source) {
0746     //    int xv_port = m_source->xvPort ();
0747     //    int xv_encoding = m_source->xvEncoding ();
0748     //    int freq = m_source->frequency ();
0749     //    cmd += QString (" -port %1 -enc %2 -norm \"%3\"").arg (xv_port).arg (xv_encoding).arg (m_source->videoNorm ());
0750     //    if (freq > 0)
0751     //        cmd += QString (" -freq %1").arg (freq);
0752     //}
0753     fprintf (stderr, "%s\n", cmd.latin1 ());
0754     *m_process << cmd;
0755     m_process->start (KProcess::NotifyOnExit, KProcess::All);
0756 
0757     return m_process->isRunning ();
0758 }
0759 
0760 XVideo::XVideo (QObject *p, ProcessInfo *pi, Settings *s)
0761  : KMPlayer::CallbackProcess (p, pi, s, "xvideo") {
0762     //m_player->settings ()->addPage (m_configpage);
0763 }
0764 
0765 XVideo::~XVideo () {}
0766 
0767 bool XVideo::ready () {
0768     if (running () || !media_object || !media_object->viewer) {
0769         setState (IProcess::Ready);
0770         return true;
0771     }
0772     return static_cast <XvProcessInfo *> (process_info)->startBackend ();
0773 }
0774 
0775 #include "kmplayervdr.moc"
0776 
0777 #include "moc_kmplayervdr.cpp"