File indexing completed on 2024-04-21 15:38:22
0001 /* This file is part of the KMPlayer application 0002 Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program; see the file COPYING. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include <qlayout.h> 0021 #include <qlabel.h> 0022 #include <qtimer.h> 0023 #include <qpushbutton.h> 0024 #include <qcheckbox.h> 0025 #include <QTableWidget> 0026 #include <qstringlist.h> 0027 #include <qcombobox.h> 0028 #include <qlineedit.h> 0029 #include <qgroupbox.h> 0030 #include <qwhatsthis.h> 0031 #include <qtabwidget.h> 0032 #include <qmessagebox.h> 0033 #include <QHeaderView> 0034 #include <QMenu> 0035 #include <QStandardPaths> 0036 #include <qfontmetrics.h> 0037 0038 #include <klocalizedstring.h> 0039 #include <kdebug.h> 0040 #include <kmessagebox.h> 0041 #include <klineedit.h> 0042 #include <kurlrequester.h> 0043 #include <kcombobox.h> 0044 #include <kconfig.h> 0045 #include <kconfiggroup.h> 0046 0047 #include "kmplayerpartbase.h" 0048 #include "kmplayerprocess.h" 0049 #include "kmplayerconfig.h" 0050 #include "kmplayertvsource.h" 0051 #include "playmodel.h" 0052 #include "playlistview.h" 0053 #include "viewarea.h" 0054 #include "kmplayer.h" 0055 #include "kmplayercontrolpanel.h" 0056 0057 static const char * strTV = "TV"; 0058 static const char * strTVDriver = "Driver"; 0059 0060 0061 KDE_NO_CDTOR_EXPORT TVDevicePage::TVDevicePage (QWidget *parent, KMPlayer::NodePtr dev) 0062 : QFrame (parent), device_doc (dev) { 0063 setObjectName("PageTVDevice"); 0064 TVDevice * device = KMPlayer::convertNode <TVDevice> (device_doc); 0065 QLabel* deviceLabel = new QLabel(i18n("Video device:") + device->src); 0066 QLabel* audioLabel = new QLabel(i18n("Audio device:")); 0067 audiodevice = new KUrlRequester (KUrl (device->getAttribute ("audio"))); 0068 QLabel* nameLabel = new QLabel(i18n("Name:")); 0069 name = new QLineEdit(device->title); 0070 QLabel *sizewidthLabel = new QLabel(i18n("Width:")); 0071 sizewidth = new QLineEdit(device->getAttribute(KMPlayer::Ids::attr_width)); 0072 QLabel* sizeheightLabel = new QLabel (i18n ("Height:")); 0073 sizeheight = new QLineEdit(device->getAttribute(KMPlayer::Ids::attr_height)); 0074 noplayback = new QCheckBox(i18n("Do not immediately play")); 0075 noplayback->setChecked (!device->getAttribute ("playback").toInt ()); 0076 noplayback->setWhatsThis(i18n("Only start playing after clicking the play button")); 0077 inputsTab = new QTabWidget; 0078 for (KMPlayer::Node *ip = device->firstChild (); ip; ip = ip->nextSibling ()) { 0079 if (ip->id != id_node_tv_input) 0080 continue; 0081 TVInput * input = KMPlayer::convertNode <TVInput> (ip); 0082 QWidget* widget = new QWidget; 0083 QHBoxLayout* tablayout = new QHBoxLayout; 0084 if (!input->getAttribute ("tuner").isEmpty ()) { 0085 QHBoxLayout* horzlayout = new QHBoxLayout; 0086 QVBoxLayout* vertlayout = new QVBoxLayout; 0087 horzlayout->addWidget(new QLabel(i18n("Norm:"))); 0088 QComboBox* norms = new QComboBox; 0089 norms->setObjectName("PageTVNorm"); 0090 norms->addItem(QString("NTSC")); 0091 norms->addItem(QString("PAL")); 0092 norms->addItem(QString("SECAM")); 0093 norms->setCurrentIndex(norms->findText(input->getAttribute ("norm"))); 0094 horzlayout->addWidget (norms); 0095 vertlayout->addLayout (horzlayout); 0096 vertlayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); 0097 QTableWidget* table = new QTableWidget(90, 2); 0098 table->setObjectName("PageTVChannels"); 0099 table->setContentsMargins(0, 0, 0, 0); 0100 QFontMetrics metrics (table->font ()); 0101 QStringList labels = QStringList() << i18n("Channel") << i18n("Frequency (MHz)"); 0102 table->setHorizontalHeaderLabels(labels); 0103 int index = 0; 0104 int first_column_width = QFontMetrics(table->horizontalHeader()->font()).boundingRect(labels[0]).width() + 20; 0105 for (KMPlayer::Node *c=input->firstChild();c;c=c->nextSibling()) { 0106 if (c->id != id_node_tv_channel) 0107 continue; 0108 int strwid = metrics.boundingRect (c->mrl ()->title).width (); 0109 if (strwid > first_column_width) 0110 first_column_width = strwid + 4; 0111 table->setItem(index, 0, new QTableWidgetItem(c->mrl()->title)); 0112 table->setItem(index++, 1, new QTableWidgetItem(KMPlayer::convertNode<TVChannel>(c)->getAttribute("frequency"))); 0113 } 0114 table->setColumnWidth (0, first_column_width); 0115 table->horizontalHeader()->setStretchLastSection(true); 0116 tablayout->addWidget (table); 0117 tablayout->addLayout (vertlayout); 0118 } 0119 widget->setLayout(tablayout); 0120 inputsTab->addTab (widget, input->mrl ()->title); 0121 } 0122 QPushButton* delButton = new QPushButton(i18n("Delete")); 0123 connect (delButton, SIGNAL (clicked ()), this, SLOT (slotDelete ())); 0124 QGridLayout* gridlayout = new QGridLayout; 0125 gridlayout->addWidget (audioLabel, 0, 0); 0126 gridlayout->addWidget (audiodevice, 0, 0, 1, 3); 0127 gridlayout->addWidget (nameLabel, 1, 0); 0128 gridlayout->addWidget (name, 1, 1, 1, 3); 0129 gridlayout->addWidget (sizewidthLabel, 2, 0); 0130 gridlayout->addWidget (sizewidth, 2, 1); 0131 gridlayout->addWidget (sizeheightLabel, 2, 2); 0132 gridlayout->addWidget (sizeheight, 2, 3); 0133 QVBoxLayout* layout = new QVBoxLayout; 0134 layout->addWidget(deviceLabel); 0135 layout->addLayout(gridlayout); 0136 layout->addWidget (inputsTab); 0137 layout->addSpacing (5); 0138 layout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum)); 0139 QHBoxLayout *buttonlayout = new QHBoxLayout (); 0140 buttonlayout->addWidget (noplayback); 0141 buttonlayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); 0142 buttonlayout->addWidget (delButton); 0143 layout->addLayout (buttonlayout); 0144 setLayout(layout); 0145 } 0146 0147 KDE_NO_EXPORT void TVDevicePage::slotDelete () { 0148 if (KMessageBox::warningYesNo (this, i18n ("You are about to remove this device from the Source menu.\nContinue?"), i18n ("Confirm")) == KMessageBox::Yes) 0149 emit deleted (this); 0150 } 0151 0152 //----------------------------------------------------------------------------- 0153 0154 KDE_NO_CDTOR_EXPORT KMPlayerPrefSourcePageTV::KMPlayerPrefSourcePageTV (QWidget *parent, KMPlayerTVSource * tvsource) 0155 : QFrame (parent), m_tvsource (tvsource) { 0156 notebook = new QTabWidget; 0157 notebook->setTabPosition (QTabWidget::South); 0158 QWidget * general = new QWidget (notebook); 0159 QLabel* driverLabel = new QLabel(i18n("Driver:")); 0160 driver = new QLineEdit; 0161 driver->setWhatsThis(i18n("dummy, v4l or bsdbt848")); 0162 QLabel *deviceLabel = new QLabel(i18n("Device:")); 0163 device = new KUrlRequester(KUrl("/dev/video")); 0164 device->setWhatsThis(i18n("Path to your video device, eg. /dev/video0")); 0165 scan = new QPushButton(i18n("Scan...")); 0166 QGridLayout *gridlayout = new QGridLayout; 0167 gridlayout->addWidget (driverLabel, 0, 0); 0168 gridlayout->addWidget (driver, 0, 1); 0169 gridlayout->addWidget (deviceLabel, 1, 0); 0170 gridlayout->addWidget (device, 1, 1); 0171 QHBoxLayout *buttonlayout = new QHBoxLayout; 0172 buttonlayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum)); 0173 buttonlayout->addWidget (scan); 0174 QVBoxLayout *layout = new QVBoxLayout; 0175 layout->addLayout(gridlayout); 0176 layout->addLayout (buttonlayout); 0177 layout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); 0178 general->setLayout(layout); 0179 notebook->addTab(general, i18n("General")); 0180 QVBoxLayout* mainlayout = new QVBoxLayout; 0181 mainlayout->addWidget(notebook); 0182 setLayout(mainlayout); 0183 } 0184 0185 KDE_NO_EXPORT void KMPlayerPrefSourcePageTV::showEvent (QShowEvent *) { 0186 m_tvsource->readXML (); 0187 } 0188 0189 //----------------------------------------------------------------------------- 0190 0191 KDE_NO_CDTOR_EXPORT TVNode::TVNode (KMPlayer::NodePtr &d, const QString & s, const char * t, short id, const QString & n) : KMPlayer::GenericMrl (d, s, n, t) { 0192 this->id = id; 0193 editable = true; 0194 } 0195 0196 KDE_NO_EXPORT void TVNode::setNodeName (const QString & nn) { 0197 title = nn; 0198 setAttribute (KMPlayer::Ids::attr_name, nn); 0199 } 0200 0201 //----------------------------------------------------------------------------- 0202 0203 KDE_NO_CDTOR_EXPORT TVChannel::TVChannel (KMPlayer::NodePtr & d, const QString & n, double freq) : TVNode (d, QString ("tv://"), "channel", id_node_tv_channel, n) { 0204 setAttribute (KMPlayer::Ids::attr_name, n); 0205 setAttribute ("frequency", QString::number (freq, 'f', 2)); 0206 } 0207 0208 KDE_NO_CDTOR_EXPORT TVChannel::TVChannel (KMPlayer::NodePtr & d) : TVNode (d, QString ("tv://"), "channel", id_node_tv_channel) { 0209 } 0210 0211 KDE_NO_EXPORT void TVChannel::closed () { 0212 title = getAttribute (KMPlayer::Ids::attr_name); 0213 Mrl::closed (); 0214 } 0215 0216 //----------------------------------------------------------------------------- 0217 0218 TVInput::TVInput (KMPlayer::NodePtr & d, const QString & n, int id) 0219 : TVNode (d, QString ("tv://"), "input", id_node_tv_input, n) { 0220 setAttribute (KMPlayer::Ids::attr_name, n); 0221 setAttribute (KMPlayer::Ids::attr_id, QString::number (id)); 0222 } 0223 0224 KDE_NO_CDTOR_EXPORT TVInput::TVInput (KMPlayer::NodePtr & d) : TVNode (d, QString ("tv://"), "input", id_node_tv_input) { 0225 } 0226 0227 KDE_NO_EXPORT KMPlayer::Node *TVInput::childFromTag (const QString & tag) { 0228 // kDebug () << nodeName () << " childFromTag " << tag; 0229 if (tag == QString::fromLatin1 ("channel")) { 0230 return new TVChannel (m_doc); 0231 } else 0232 return 0L; 0233 } 0234 0235 KDE_NO_EXPORT void TVInput::closed () { 0236 //title = getAttribute (KMPlayer::Ids::attr_name); 0237 Mrl::closed (); 0238 } 0239 0240 KDE_NO_EXPORT void TVInput::setNodeName (const QString & name) { 0241 Node *p = parentNode (); 0242 QString nm (name); 0243 if (p && p->id == id_node_tv_device) { 0244 int pos = name.indexOf (QString (" - ") + p->mrl ()->title); 0245 if (pos > -1) 0246 nm.truncate (pos); 0247 } 0248 title = nm + QString (" - ") + title; 0249 TVNode::setNodeName (nm); 0250 } 0251 0252 //----------------------------------------------------------------------------- 0253 0254 KDE_NO_CDTOR_EXPORT TVDevice::TVDevice (KMPlayer::NodePtr & doc, const QString & d) : TVNode (doc, d, "device", id_node_tv_device), zombie (false) { 0255 setAttribute ("path", d); 0256 } 0257 0258 KDE_NO_CDTOR_EXPORT TVDevice::TVDevice (KMPlayer::NodePtr & doc) 0259 : TVNode (doc, i18n ("tv device"), "device", id_node_tv_device), zombie (false) { 0260 } 0261 0262 KDE_NO_CDTOR_EXPORT TVDevice::~TVDevice () { 0263 if (device_page) 0264 device_page->deleteLater (); 0265 } 0266 0267 KDE_NO_EXPORT KMPlayer::Node *TVDevice::childFromTag (const QString & tag) { 0268 // kDebug () << nodeName () << " childFromTag " << tag; 0269 if (tag == QString::fromLatin1 ("input")) 0270 return new TVInput (m_doc); 0271 return 0L; 0272 } 0273 0274 KDE_NO_EXPORT void TVDevice::closed () { 0275 updateNodeName (); 0276 Mrl::closed (); 0277 } 0278 0279 KDE_NO_EXPORT void TVDevice::message (KMPlayer::MessageType msg, void *data) { 0280 if (KMPlayer::MsgChildFinished == msg) 0281 finish (); 0282 else 0283 TVNode::message (msg, data); 0284 } 0285 0286 void *TVDevice::role (KMPlayer::RoleType msg, void *content) 0287 { 0288 if (KMPlayer::RolePlaylist == msg) 0289 return NULL; 0290 return TVNode::role (msg, content); 0291 } 0292 0293 KDE_NO_EXPORT void TVDevice::setNodeName (const QString & name) { 0294 TVNode::setNodeName (name); 0295 updateNodeName (); 0296 } 0297 0298 KDE_NO_EXPORT void TVDevice::updateNodeName () { 0299 title = getAttribute (KMPlayer::Ids::attr_name); 0300 src = getAttribute ("path"); 0301 for (KMPlayer::Node *c = firstChild (); c; c = c->nextSibling ()) 0302 if (c->id == id_node_tv_input) { 0303 TVInput * i = static_cast <TVInput *> (c); 0304 i->title = i->getAttribute (KMPlayer::Ids::attr_name) + 0305 QString (" - ") + title; 0306 } 0307 } 0308 0309 KDE_NO_EXPORT void TVDevice::updateDevicePage () { 0310 if (!device_page) 0311 return; 0312 title = device_page->name->text (); 0313 setAttribute (KMPlayer::Ids::attr_name, title); 0314 setAttribute ("audio", device_page->audiodevice->lineEdit()->text ()); 0315 setAttribute ("playback", device_page->noplayback->isChecked() ? "0" : "1"); 0316 setAttribute (KMPlayer::Ids::attr_width, device_page->sizewidth->text ()); 0317 setAttribute (KMPlayer::Ids::attr_height, device_page->sizeheight->text ()); 0318 int i = 0; 0319 for (KMPlayer::Node *ip = firstChild(); ip; ip=ip->nextSibling(),++i) { 0320 if (ip->id != id_node_tv_input) 0321 continue; 0322 TVInput * input = KMPlayer::convertNode <TVInput> (ip); 0323 bool ok; 0324 if (input->getAttribute ("tuner").toInt (&ok) && ok) { 0325 QWidget* widget = device_page->inputsTab->widget(i); 0326 QTableWidget* table = static_cast<QTableWidget*>(widget->findChild<QTableWidget*>("PageTVChannels")); 0327 if (table) { 0328 input->clearChildren (); 0329 for (int j = 0; j<table->rowCount() && table->item (j, 1); ++j) { 0330 input->appendChild (new TVChannel (m_doc, table->item (j, 0)->text (), table->item (j, 1)->text ().toDouble ())); 0331 } 0332 } 0333 QComboBox* norms = static_cast<QComboBox*>(widget->findChild<QComboBox*>("PageTVNorm")); 0334 if (norms) { 0335 input->setAttribute ("norm", norms->currentText ()); 0336 } 0337 } 0338 } 0339 } 0340 0341 //----------------------------------------------------------------------------- 0342 0343 KDE_NO_CDTOR_EXPORT 0344 TVDocument::TVDocument (KMPlayerTVSource * source) 0345 : FileDocument (id_node_tv_document, "tv://", source), m_source (source) { 0346 title = i18n ("Television"); 0347 bookmarkable = false; 0348 } 0349 0350 KDE_NO_EXPORT KMPlayer::Node *TVDocument::childFromTag (const QString & tag) { 0351 // kDebug () << nodeName () << " childFromTag " << tag; 0352 if (tag == QString::fromLatin1 ("device")) 0353 return new TVDevice (m_doc); 0354 return FileDocument::childFromTag (tag); 0355 } 0356 0357 KDE_NO_EXPORT void TVDocument::message (KMPlayer::MessageType msg, void *data) { 0358 if (KMPlayer::MsgChildFinished == msg) 0359 finish (); 0360 else 0361 FileDocument::message (msg, data); 0362 } 0363 0364 KDE_NO_EXPORT void TVDocument::defer () { 0365 if (!resolved) { 0366 resolved = true; 0367 readFromFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kmplayer/tv.xml"); 0368 } 0369 } 0370 0371 //----------------------------------------------------------------------------- 0372 0373 KDE_NO_CDTOR_EXPORT KMPlayerTVSource::KMPlayerTVSource(KMPlayerApp* a) 0374 : KMPlayer::Source (i18n ("TV"), a->player(), "tvsource"), m_app(a), m_configpage(0L), scanner(0L), config_read(false) { 0375 m_url = "tv://"; 0376 m_document = new TVDocument (this); 0377 m_player->settings ()->addPage (this); 0378 tree_id = m_player->playModel()->addTree (m_document, "tvsource", "video-television", KMPlayer::PlayModel::TreeEdit | KMPlayer::PlayModel::Moveable | KMPlayer::PlayModel::Deleteable); 0379 } 0380 0381 KDE_NO_CDTOR_EXPORT KMPlayerTVSource::~KMPlayerTVSource () { 0382 static_cast <TVDocument *> (m_document.ptr ())->sync 0383 (QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kmplayer/tv.xml"); 0384 } 0385 0386 KDE_NO_EXPORT void KMPlayerTVSource::activate () { 0387 m_identified = true; 0388 //if (m_player->settings ()->showbroadcastbutton) 0389 // m_app->view()->controlPanel()->broadcastButton ()->show (); 0390 if (m_cur_tvdevice && !m_current) { 0391 for (KMPlayer::Node *i = m_cur_tvdevice->firstChild(); i && !m_current; i=i->nextSibling()) 0392 if (i->id == id_node_tv_input) { 0393 TVInput * input = KMPlayer::convertNode <TVInput> (i); 0394 bool ok; 0395 m_cur_tvinput = i; 0396 if (input->getAttribute ("tuner").toInt (&ok) && ok) { 0397 for (KMPlayer::Node *c = i->firstChild (); c; c = c->nextSibling ()) 0398 if (c->id == id_node_tv_channel) { 0399 setCurrent (c->mrl ()); 0400 break; 0401 } 0402 } else 0403 m_current = i; 0404 } 0405 } else if (!m_cur_tvdevice) 0406 KMPlayer::Source::reset (); 0407 if (m_cur_tvdevice) { 0408 QString playback = static_cast <KMPlayer::Element *> (m_cur_tvdevice.ptr ())->getAttribute (QString::fromLatin1 ("playback")); 0409 if (playback.isEmpty () || playback.toInt ()) 0410 QTimer::singleShot (0, m_player, SLOT (play ())); 0411 } 0412 } 0413 /* TODO: playback by 0414 * ffmpeg -vd /dev/video0 -r 25 -s 768x576 -f rawvideo - |mplayer -nocache -ao arts -rawvideo on:w=768:h=576:fps=25 -quiet - 0415 */ 0416 0417 KDE_NO_EXPORT void KMPlayerTVSource::deactivate () { 0418 //if (m_player->view () && !m_app->view ()->controlPanel()->broadcastButton ()->isOn ()) 0419 // m_app->view ()->controlPanel()->broadcastButton ()->hide (); 0420 reset (); 0421 } 0422 0423 void KMPlayerTVSource::play (KMPlayer::Mrl *mrl) { 0424 if (mrl && mrl->id == id_node_tv_document) { 0425 readXML (); 0426 } else { 0427 m_current = mrl; 0428 for (KMPlayer::Node *e = mrl; e; e = e->parentNode ()) { 0429 if (e->id == id_node_tv_device) { 0430 m_cur_tvdevice = e; 0431 break; 0432 } else if (e->id == id_node_tv_input) 0433 m_cur_tvinput = e; 0434 } 0435 if (m_player->source () != this) 0436 m_player->setSource (this); 0437 else 0438 KMPlayer::Source::play (mrl); 0439 /*else if (m_player->process ()->playing ()) { 0440 //m_back_request = m_current; 0441 m_player->process ()->stop (); 0442 } else { 0443 buildArguments (); 0444 if (m_app->broadcasting ()) 0445 QTimer::singleShot (0, m_app->broadcastConfig (), SLOT (startFeed ())); 0446 else 0447 KMPlayer::Source::play (mrl); 0448 }*/ 0449 } 0450 } 0451 0452 KDE_NO_EXPORT KMPlayer::NodePtr KMPlayerTVSource::root () { 0453 return m_cur_tvinput; 0454 } 0455 0456 KDE_NO_EXPORT void KMPlayerTVSource::setCurrent (KMPlayer::Mrl *mrl) { 0457 TVChannel * channel = 0L; 0458 TVInput * input = 0L; 0459 m_current = mrl; 0460 KMPlayer::NodePtr elm = m_current; 0461 if (elm && elm->id == id_node_tv_channel) { 0462 channel = KMPlayer::convertNode <TVChannel> (elm); 0463 elm = elm->parentNode (); 0464 } 0465 if (elm && elm->id == id_node_tv_input) 0466 input = KMPlayer::convertNode <TVInput> (elm); 0467 if (!(channel || (input && input->getAttribute ("tuner").isEmpty ()))) 0468 return; 0469 m_cur_tvinput = input; 0470 m_cur_tvdevice = input->parentNode (); 0471 m_player->playModel()->updateTree(0, m_cur_tvinput, m_current, true, false); 0472 if (m_cur_tvdevice->id != id_node_tv_device) { 0473 return; 0474 } 0475 TVDevice * tvdevice = KMPlayer::convertNode <TVDevice> (m_cur_tvdevice); 0476 m_identified = true; 0477 m_audiodevice = tvdevice->getAttribute ("audio"); 0478 m_videodevice = tvdevice->src; 0479 m_videonorm = input->getAttribute ("norm"); 0480 m_tuner = input->getAttribute (KMPlayer::Ids::attr_name); 0481 QString xvport = tvdevice->getAttribute ("xvport"); 0482 if (!xvport.isEmpty ()) 0483 m_xvport = xvport.toInt (); 0484 QString xvenc = input->getAttribute ("xvenc"); 0485 if (!xvenc.isEmpty ()) 0486 m_xvencoding = xvenc.toInt (); 0487 QString command; 0488 command.sprintf ("device=%s:input=%s", 0489 tvdevice->src.toAscii ().data (), 0490 input->getAttribute (KMPlayer::Ids::attr_id).toAscii ().data ()); 0491 if (channel) { 0492 QString freq = channel->getAttribute ("frequency"); 0493 m_frequency = (int)(1000 * freq.toDouble ()); 0494 command += QString (":freq=%1").arg (freq); 0495 } else 0496 m_frequency = 0; 0497 if (!m_videonorm.isEmpty ()) 0498 command += QString (":norm=%1").arg (m_videonorm); 0499 m_app->setCaption (i18n ("TV: ") + (channel ? channel->mrl ()->title : input->mrl ()->title), false); 0500 setDimensions (m_cur_tvdevice, 0501 tvdevice->getAttribute (KMPlayer::Ids::attr_width).toInt (), 0502 tvdevice->getAttribute (KMPlayer::Ids::attr_height).toInt ()); 0503 m_options.sprintf ("-tv noaudio:driver=%s:%s:width=%d:height=%d -slave -nocache -quiet", tvdriver.toAscii ().data (), command.toAscii ().data (), width (), height ()); 0504 m_recordcmd.sprintf ("-tv %s:driver=%s:%s:width=%d:height=%d", m_audiodevice.isEmpty () ? "noaudio" : QString(QLatin1String ("forceaudio:adevice=") + m_audiodevice).toAscii ().data(), tvdriver.toAscii ().data (), command.toAscii ().data (), width (), height ()); 0505 } 0506 0507 KDE_NO_EXPORT void KMPlayerTVSource::menuClicked (int id) { 0508 KMPlayer::Node *elm = m_document->firstChild (); 0509 for (; id > 0; --id, elm = elm->nextSibling ()) 0510 ; 0511 m_cur_tvdevice = elm; 0512 m_cur_tvinput = elm->firstChild (); // FIXME 0513 m_current = 0L; 0514 m_player->setSource (this); 0515 } 0516 0517 KDE_NO_EXPORT QString KMPlayerTVSource::filterOptions () { 0518 if (! m_player->settings ()->disableppauto) 0519 return KMPlayer::Source::filterOptions (); 0520 return QString ("-vf pp=lb"); 0521 } 0522 0523 KDE_NO_EXPORT bool KMPlayerTVSource::hasLength () { 0524 return false; 0525 } 0526 0527 KDE_NO_EXPORT bool KMPlayerTVSource::isSeekable () { 0528 return true; 0529 } 0530 0531 KDE_NO_EXPORT QString KMPlayerTVSource::prettyName () { 0532 QString name (i18n ("TV")); 0533 //if (m_tvsource) 0534 // name += ' ' + m_tvsource->title; 0535 return name; 0536 } 0537 0538 KDE_NO_EXPORT void KMPlayerTVSource::write (KSharedConfigPtr m_config) { 0539 if (!config_read) return; 0540 KConfigGroup (m_config, strTV).writeEntry (strTVDriver, tvdriver); 0541 static_cast <TVDocument *> (m_document.ptr ())->writeToFile 0542 (QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kmplayer/tv.xml"); 0543 kDebug () << "KMPlayerTVSource::write XML"; 0544 } 0545 0546 KDE_NO_EXPORT void KMPlayerTVSource::readXML () { 0547 if (config_read) return; 0548 config_read = true; 0549 kDebug () << "KMPlayerTVSource::readXML"; 0550 m_document->defer (); 0551 m_player->playModel()->updateTree (tree_id, m_document, 0, false, false); 0552 sync (false); 0553 } 0554 0555 KDE_NO_EXPORT void KMPlayerTVSource::read (KSharedConfigPtr m_config) { 0556 tvdriver = KConfigGroup (m_config, strTV).readEntry ( 0557 strTVDriver, QString ("v4l2")); 0558 } 0559 0560 KDE_NO_EXPORT void KMPlayerTVSource::sync (bool fromUI) { 0561 if (!m_configpage) return; 0562 if (m_document && m_document->hasChildNodes ()) 0563 m_app->showBroadcastConfig (); 0564 else 0565 m_app->hideBroadcastConfig (); 0566 if (fromUI) { 0567 tvdriver = m_configpage->driver->text (); 0568 for (KMPlayer::Node *d=m_document->firstChild();d; d=d->nextSibling()) 0569 if (d->id == id_node_tv_device) 0570 static_cast <TVDevice *> (d)->updateDevicePage (); 0571 m_player->playModel()->updateTree(tree_id, m_document, 0, false, false); 0572 } else { 0573 m_configpage->driver->setText (tvdriver); 0574 for (KMPlayer::Node *dp = m_document->firstChild (); dp; dp = dp->nextSibling ()) 0575 if (dp->id == id_node_tv_device) 0576 addTVDevicePage (KMPlayer::convertNode <TVDevice> (dp)); 0577 } 0578 } 0579 0580 KDE_NO_EXPORT void KMPlayerTVSource::prefLocation (QString & item, QString & icon, QString & tab) { 0581 item = i18n ("Source"); 0582 icon = QString ("source"); 0583 tab = i18n ("TV"); 0584 } 0585 0586 KDE_NO_EXPORT QFrame * KMPlayerTVSource::prefPage (QWidget * parent) { 0587 if (!m_configpage) { 0588 m_configpage = new KMPlayerPrefSourcePageTV (parent, this); 0589 scanner = new TVDeviceScannerSource (this); 0590 connect (m_configpage->scan, SIGNAL(clicked()), this, SLOT(slotScan())); 0591 } 0592 return m_configpage; 0593 } 0594 0595 static bool hasTVDevice (KMPlayer::NodePtr doc, const QString & devstr) { 0596 for (KMPlayer::Node *e = doc->firstChild (); e; e = e->nextSibling ()) 0597 if (e->id == id_node_tv_device && 0598 static_cast <TVDevice *> (e)->src == devstr) 0599 return true; 0600 return false; 0601 } 0602 0603 KDE_NO_EXPORT void KMPlayerTVSource::slotScan () { 0604 QString devstr = m_configpage->device->lineEdit()->text (); 0605 if (!hasTVDevice(m_document, devstr)) { 0606 scanner->scan (devstr, m_configpage->driver->text()); 0607 connect (scanner, SIGNAL (scanFinished (TVDevice *)), 0608 this, SLOT (slotScanFinished (TVDevice *))); 0609 } else 0610 KMessageBox::error (m_configpage, i18n ("Device already present."), 0611 i18n ("Error")); 0612 } 0613 0614 KDE_NO_EXPORT void KMPlayerTVSource::slotScanFinished (TVDevice * tvdevice) { 0615 disconnect (scanner, SIGNAL (scanFinished (TVDevice *)), 0616 this, SLOT (slotScanFinished (TVDevice *))); 0617 if (tvdevice) { 0618 tvdevice->zombie = false; 0619 addTVDevicePage (tvdevice, true); 0620 m_player->playModel()->updateTree(tree_id, m_document, 0, false, false); 0621 } else 0622 KMessageBox::error(m_configpage,i18n("No device found."),i18n("Error")); 0623 } 0624 0625 KDE_NO_EXPORT void KMPlayerTVSource::addTVDevicePage(TVDevice *dev, bool show) { 0626 if (dev->device_page) 0627 dev->device_page->deleteLater (); 0628 dev->device_page = new TVDevicePage (m_configpage->notebook, dev); 0629 m_configpage->notebook->addTab(dev->device_page, dev->title); 0630 connect (dev->device_page, SIGNAL (deleted (TVDevicePage *)), 0631 this, SLOT (slotDeviceDeleted (TVDevicePage *))); 0632 if (show) 0633 m_configpage->notebook->setCurrentIndex(m_configpage->notebook->count()-1); 0634 } 0635 0636 KDE_NO_EXPORT void KMPlayerTVSource::slotDeviceDeleted (TVDevicePage *devpage) { 0637 m_document->removeChild (devpage->device_doc); 0638 m_configpage->notebook->setCurrentIndex(0); 0639 m_player->playModel()->updateTree (tree_id, m_document, 0, false, false); 0640 } 0641 0642 //----------------------------------------------------------------------------- 0643 0644 KDE_NO_CDTOR_EXPORT TVDeviceScannerSource::TVDeviceScannerSource (KMPlayerTVSource * src) 0645 : KMPlayer::Source (i18n ("TVScanner"), src->player (), "tvscanner"), 0646 m_tvsource (src), 0647 m_tvdevice (0L), 0648 m_process (NULL), 0649 m_viewer (NULL) { 0650 } 0651 0652 KDE_NO_EXPORT void TVDeviceScannerSource::init () { 0653 } 0654 0655 KDE_NO_EXPORT bool TVDeviceScannerSource::processOutput (const QString & line) { 0656 if (m_nameRegExp.indexIn(line) > -1) { 0657 m_tvdevice->title = m_nameRegExp.cap (1); 0658 m_tvdevice->setAttribute(KMPlayer::Ids::attr_name,m_tvdevice->title); 0659 kDebug() << "Name " << m_tvdevice->title; 0660 } else if (m_sizesRegExp.indexIn(line) > -1) { 0661 m_tvdevice->setAttribute (KMPlayer::Ids::attr_width, 0662 m_sizesRegExp.cap(1)); 0663 m_tvdevice->setAttribute (KMPlayer::Ids::attr_height, 0664 m_sizesRegExp.cap(2)); 0665 m_tvdevice->setAttribute ("minwidth", m_sizesRegExp.cap (1)); 0666 m_tvdevice->setAttribute ("minheight", m_sizesRegExp.cap (2)); 0667 m_tvdevice->setAttribute ("maxwidth", m_sizesRegExp.cap (3)); 0668 m_tvdevice->setAttribute ("maxheight", m_sizesRegExp.cap (4)); 0669 } else if (m_inputRegExp.indexIn(line) > -1) { 0670 KMPlayer::NodePtr doc = m_tvsource->document (); 0671 TVInput * input = new TVInput (doc, m_inputRegExp.cap(2).trimmed(), 0672 m_inputRegExp.cap (1).toInt ()); 0673 if (m_inputRegExp.cap (3).toInt () == 1) 0674 input->setAttribute ("tuner", "1"); 0675 m_tvdevice->appendChild (input); 0676 kDebug() << "Input " << input->mrl ()->title; 0677 } else if (m_inputRegExpV4l2.indexIn(line) > -1) { 0678 KMPlayer::NodePtr doc = m_tvsource->document (); 0679 QStringList sl = m_inputRegExpV4l2.cap(1).split (QChar (';')); 0680 const QStringList::iterator e = sl.end (); 0681 for (QStringList::iterator i = sl.begin (); i != e; ++i) { 0682 int pos = (*i).indexOf (QChar ('=')); 0683 if (pos > 0) { 0684 int id = (*i).left (pos).trimmed ().toInt (); 0685 TVInput *input = new TVInput(doc,(*i).mid(pos+1).trimmed(), id); 0686 if (!id && m_caps.indexOf ("tuner") > -1) 0687 input->setAttribute ("tuner", "1"); 0688 m_tvdevice->appendChild (input); 0689 } 0690 } 0691 } else { 0692 int pos = line.indexOf ("Capabilites:"); 0693 if (pos > 0) 0694 m_caps = line.mid (pos + 12); 0695 return false; 0696 } 0697 return true; 0698 } 0699 0700 KDE_NO_EXPORT QString TVDeviceScannerSource::filterOptions () { 0701 return QString (""); 0702 } 0703 0704 KDE_NO_EXPORT bool TVDeviceScannerSource::hasLength () { 0705 return false; 0706 } 0707 0708 KDE_NO_EXPORT bool TVDeviceScannerSource::isSeekable () { 0709 return false; 0710 } 0711 0712 KDE_NO_EXPORT bool TVDeviceScannerSource::scan (const QString & dev, const QString & dri) { 0713 if (m_tvdevice) 0714 return false; 0715 setUrl ("tv://"); 0716 KMPlayer::NodePtr doc = m_tvsource->document (); 0717 m_tvdevice = new TVDevice (doc, dev); 0718 m_tvsource->document ()->appendChild (m_tvdevice); 0719 m_tvdevice->zombie = true; // not for real yet 0720 m_driver = dri; 0721 m_old_source = m_tvsource->player ()->source (); 0722 m_tvsource->player ()->setSource (this); 0723 m_identified = true; 0724 play (m_tvdevice); 0725 return true; 0726 } 0727 0728 KDE_NO_EXPORT void TVDeviceScannerSource::activate () { 0729 m_nameRegExp.setPattern ("Selected device:\\s*([^\\s].*)"); 0730 m_sizesRegExp.setPattern ("Supported sizes:\\s*([0-9]+)x([0-9]+) => ([0-9]+)x([0-9]+)"); 0731 m_inputRegExp.setPattern ("\\s*([0-9]+):\\s*([^:]+):[^\\(]*\\(tuner:([01]),\\s*norm:([^\\)]+)\\)"); 0732 m_inputRegExpV4l2.setPattern ("inputs:((?:\\s*[0-9]+\\s*=\\s*[^;]+;)+)"); 0733 } 0734 0735 KDE_NO_EXPORT void TVDeviceScannerSource::deactivate () { 0736 kDebug () << "TVDeviceScannerSource::deactivate"; 0737 if (m_tvdevice) { 0738 if (m_tvdevice->parentNode ()) 0739 m_tvdevice->parentNode ()->removeChild (m_tvdevice); 0740 m_tvdevice = 0L; 0741 delete m_process; 0742 emit scanFinished (m_tvdevice); 0743 } 0744 } 0745 0746 KDE_NO_EXPORT void TVDeviceScannerSource::play (KMPlayer::Mrl *) { 0747 if (!m_tvdevice) 0748 return; 0749 m_options.sprintf ("tv:// -tv driver=%s:device=%s -identify -frames 0", m_driver.toAscii ().data (), m_tvdevice->src.toAscii ().data ()); 0750 m_tvsource->player ()->stop (); 0751 KMPlayer::Node *n = new KMPlayer::SourceDocument (this, QString ()); 0752 setDocument (n, n); 0753 m_process = m_player->mediaManager()->processInfos()["mplayer"]->create (m_player, this); 0754 m_viewer = m_player->viewWidget ()->viewArea ()->createVideoWidget (); 0755 m_process->ready (); 0756 } 0757 0758 KDE_NO_EXPORT void TVDeviceScannerSource::scanningFinished () { 0759 TVDevice * dev = 0L; 0760 delete m_process; 0761 kDebug () << "scanning done " << m_tvdevice->hasChildNodes (); 0762 if (!m_tvdevice->hasChildNodes ()) { 0763 m_tvsource->document ()->removeChild (m_tvdevice); 0764 } else { 0765 dev = m_tvdevice; 0766 if (width () > 0 && height () > 0) { 0767 m_tvdevice->setAttribute (KMPlayer::Ids::attr_width, 0768 QString::number (width ())); 0769 m_tvdevice->setAttribute (KMPlayer::Ids::attr_height, 0770 QString::number (height ())); 0771 } 0772 } 0773 m_tvdevice = 0L; 0774 m_player->setSource (m_old_source); 0775 emit scanFinished (dev); 0776 } 0777 0778 void TVDeviceScannerSource::stateChange (KMPlayer::IProcess *, 0779 KMPlayer::IProcess::State os, KMPlayer::IProcess::State ns) { 0780 if (KMPlayer::IProcess::Ready == ns) { 0781 if (os > KMPlayer::IProcess::Ready) 0782 QTimer::singleShot (0, this, SLOT (scanningFinished())); 0783 else if (m_process && os < KMPlayer::IProcess::Ready) 0784 m_process->play (); 0785 } 0786 } 0787 0788 void TVDeviceScannerSource::processDestroyed (KMPlayer::IProcess *) { 0789 m_process = NULL; 0790 KMPlayer::View *view = m_player->viewWidget (); 0791 if (view) 0792 view->viewArea ()->destroyVideoWidget (m_viewer); 0793 m_viewer = NULL; 0794 } 0795 0796 KMPlayer::IViewer *TVDeviceScannerSource::viewer () { 0797 return m_viewer; 0798 } 0799 0800 KMPlayer::Mrl *TVDeviceScannerSource::getMrl () { 0801 return document ()->mrl (); 0802 } 0803 0804 0805 #include "kmplayertvsource.moc"