You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmplayer/src/kmplayertvsource.cpp

738 lines
30 KiB

/* This file is part of the KMPlayer application
Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqtimer.h>
#include <tqpushbutton.h>
#include <tqcheckbox.h>
#include <tqtable.h>
#include <tqstringlist.h>
#include <tqcombobox.h>
#include <tqlineedit.h>
#include <tqgroupbox.h>
#include <tqwhatsthis.h>
#include <tqtabwidget.h>
#include <tqmessagebox.h>
#include <tqpopupmenu.h>
#include <tqfontmetrics.h>
#include <klocale.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <klineedit.h>
#include <kurlrequester.h>
#include <kcombobox.h>
#include <kconfig.h>
#include <kstandarddirs.h>
#include "kmplayerpartbase.h"
#include "kmplayerprocess.h"
#include "kmplayerconfig.h"
#include "kmplayertvsource.h"
#include "playlistview.h"
#include "kmplayer.h"
#include "kmplayercontrolpanel.h"
#include "kmplayerbroadcast.h"
static const char * strTV = "TV";
static const char * strTVDriver = "Driver";
KDE_NO_CDTOR_EXPORT TVDevicePage::TVDevicePage (TQWidget *parent, KMPlayer::NodePtr dev)
: TQFrame (parent, "PageTVDevice"), device_doc (dev) {
TVDevice * device = KMPlayer::convertNode <TVDevice> (device_doc);
TQVBoxLayout *layout = new TQVBoxLayout (this, 5, 2);
TQLabel * deviceLabel = new TQLabel (i18n ("Video device:") + device->src, this, 0);
layout->addWidget (deviceLabel);
TQGridLayout *gridlayout = new TQGridLayout (layout, 3, 4);
TQLabel * audioLabel = new TQLabel (i18n ("Audio device:"), this);
audiodevice = new KURLRequester (device->getAttribute ("audio"), this);
TQLabel * nameLabel = new TQLabel (i18n ("Name:"), this, 0);
name = new TQLineEdit (device->pretty_name, this, 0);
TQLabel *sizewidthLabel = new TQLabel (i18n ("Width:"), this, 0);
sizewidth = new TQLineEdit (device->getAttribute (KMPlayer::StringPool::attr_width), this, 0);
TQLabel *sizeheightLabel = new TQLabel (i18n ("Height:"), this, 0);
sizeheight = new TQLineEdit (device->getAttribute (KMPlayer::StringPool::attr_height), this, 0);
noplayback = new TQCheckBox (i18n ("Do not immediately play"), this);
noplayback->setChecked (!device->getAttribute ("playback").toInt ());
TQWhatsThis::add (noplayback, i18n ("Only start playing after clicking the play button"));
inputsTab = new TQTabWidget (this);
for (KMPlayer::NodePtr ip = device->firstChild (); ip; ip = ip->nextSibling ()) {
if (ip->id != id_node_tv_input)
continue;
TVInput * input = KMPlayer::convertNode <TVInput> (ip);
TQWidget * widget = new TQWidget (this);
TQHBoxLayout *tablayout = new TQHBoxLayout (widget, 5, 2);
if (!input->getAttribute ("tuner").isEmpty ()) {
TQHBoxLayout *horzlayout = new TQHBoxLayout ();
TQVBoxLayout *vertlayout = new TQVBoxLayout ();
horzlayout->addWidget (new TQLabel (i18n ("Norm:"), widget));
TQComboBox * norms = new TQComboBox (widget, "PageTVNorm");
norms->insertItem (TQString ("NTSC"), 0);
norms->insertItem (TQString ("PAL"), 1);
norms->insertItem (TQString ("SECAM"), 2);
norms->setCurrentText (input->getAttribute ("norm"));
horzlayout->addWidget (norms);
vertlayout->addLayout (horzlayout);
vertlayout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding));
TQTable * table = new TQTable (90, 2, widget, "PageTVChannels");
TQFontMetrics metrics (table->font ());
TQHeader *header = table->horizontalHeader();
header->setLabel (0, i18n ("Channel"));
header->setLabel (1, i18n ("Frequency (MHz)"));
int index = 0;
int first_column_width = TQFontMetrics (header->font ()).boundingRect (header->label (0)).width () + 20;
for (KMPlayer::NodePtr c=input->firstChild();c;c=c->nextSibling()) {
if (c->id != id_node_tv_channel)
continue;
int strwid = metrics.boundingRect (c->mrl ()->pretty_name).width ();
if (strwid > first_column_width)
first_column_width = strwid + 4;
table->setItem (index, 0, new TQTableItem (table, TQTableItem::Always, c->mrl ()->pretty_name));
table->setItem (index++, 1, new TQTableItem (table, TQTableItem::Always, KMPlayer::convertNode<TVChannel>(c)->getAttribute ("frequency")));
}
table->setColumnWidth (0, first_column_width);
table->setColumnStretchable (1, true);
tablayout->addWidget (table);
tablayout->addLayout (vertlayout);
}
inputsTab->addTab (widget, input->mrl ()->pretty_name);
}
TQPushButton * delButton = new TQPushButton (i18n ("Delete"), this);
connect (delButton, TQT_SIGNAL (clicked ()), this, TQT_SLOT (slotDelete ()));
gridlayout->addWidget (audioLabel, 0, 0);
gridlayout->addMultiCellWidget (audiodevice, 0, 0, 1, 3);
gridlayout->addWidget (nameLabel, 1, 0);
gridlayout->addMultiCellWidget (name, 1, 1, 1, 3);
gridlayout->addWidget (sizewidthLabel, 2, 0);
gridlayout->addWidget (sizewidth, 2, 1);
gridlayout->addWidget (sizeheightLabel, 2, 2);
gridlayout->addWidget (sizeheight, 2, 3);
layout->addWidget (inputsTab);
layout->addSpacing (5);
layout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Minimum, TQSizePolicy::Minimum));
TQHBoxLayout *buttonlayout = new TQHBoxLayout ();
buttonlayout->addWidget (noplayback);
buttonlayout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
buttonlayout->addWidget (delButton);
layout->addLayout (buttonlayout);
}
KDE_NO_EXPORT void TVDevicePage::slotDelete () {
if (KMessageBox::warningYesNo (this, i18n ("You are about to remove this device from the Source menu.\nContinue?"), i18n ("Confirm")) == KMessageBox::Yes)
emit deleted (this);
}
//-----------------------------------------------------------------------------
KDE_NO_CDTOR_EXPORT KMPlayerPrefSourcePageTV::KMPlayerPrefSourcePageTV (TQWidget *parent, KMPlayerTVSource * tvsource)
: TQFrame (parent), m_tvsource (tvsource) {
TQVBoxLayout * mainlayout = new TQVBoxLayout (this, 5);
notebook = new TQTabWidget (this);
notebook->setTabPosition (TQTabWidget::Bottom);
mainlayout->addWidget (notebook);
TQWidget * general = new TQWidget (notebook);
TQVBoxLayout *layout = new TQVBoxLayout (general);
TQGridLayout *gridlayout = new TQGridLayout (layout, 2, 2, 2);
TQLabel *driverLabel = new TQLabel (i18n ("Driver:"), general, 0);
driver = new TQLineEdit ("", general, 0);
TQWhatsThis::add (driver, i18n ("dummy, v4l or bsdbt848"));
TQLabel *deviceLabel = new TQLabel (i18n ("Device:"), general, 0);
device = new KURLRequester ("/dev/video", general);
TQWhatsThis::add(device, i18n("Path to your video device, eg. /dev/video0"));
scan = new TQPushButton (i18n ("Scan..."), general);
gridlayout->addWidget (driverLabel, 0, 0);
gridlayout->addWidget (driver, 0, 1);
gridlayout->addWidget (deviceLabel, 1, 0);
gridlayout->addWidget (device, 1, 1);
TQHBoxLayout *buttonlayout = new TQHBoxLayout ();
buttonlayout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Minimum, TQSizePolicy::Minimum));
buttonlayout->addWidget (scan);
layout->addLayout (buttonlayout);
layout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding));
notebook->insertTab (general, i18n ("General"));
}
KDE_NO_EXPORT void KMPlayerPrefSourcePageTV::showEvent (TQShowEvent *) {
m_tvsource->readXML ();
}
//-----------------------------------------------------------------------------
KDE_NO_CDTOR_EXPORT TVNode::TVNode (KMPlayer::NodePtr &d, const TQString & s, const char * t, short id, const TQString & n) : KMPlayer::GenericMrl (d, s, n, t) {
this->id = id;
editable = true;
}
KDE_NO_EXPORT void TVNode::setNodeName (const TQString & nn) {
pretty_name = nn;
setAttribute (KMPlayer::StringPool::attr_name, nn);
}
//-----------------------------------------------------------------------------
KDE_NO_CDTOR_EXPORT TVChannel::TVChannel (KMPlayer::NodePtr & d, const TQString & n, double freq) : TVNode (d, TQString ("tv://"), "channel", id_node_tv_channel, n) {
setAttribute (KMPlayer::StringPool::attr_name, n);
setAttribute ("frequency", TQString::number (freq, 'f', 2));
}
KDE_NO_CDTOR_EXPORT TVChannel::TVChannel (KMPlayer::NodePtr & d) : TVNode (d, TQString ("tv://"), "channel", id_node_tv_channel) {
}
KDE_NO_EXPORT void TVChannel::closed () {
pretty_name = getAttribute (KMPlayer::StringPool::attr_name);
}
//-----------------------------------------------------------------------------
TVInput::TVInput (KMPlayer::NodePtr & d, const TQString & n, int id)
: TVNode (d, TQString ("tv://"), "input", id_node_tv_input, n) {
setAttribute (KMPlayer::StringPool::attr_name, n);
setAttribute (KMPlayer::StringPool::attr_id, TQString::number (id));
}
KDE_NO_CDTOR_EXPORT TVInput::TVInput (KMPlayer::NodePtr & d) : TVNode (d, TQString ("tv://"), "input", id_node_tv_input) {
}
KDE_NO_EXPORT KMPlayer::NodePtr TVInput::childFromTag (const TQString & tag) {
// kdDebug () << nodeName () << " childFromTag " << tag << endl;
if (tag == TQString::fromLatin1 ("channel")) {
return new TVChannel (m_doc);
} else
return 0L;
}
KDE_NO_EXPORT void TVInput::closed () {
//pretty_name = getAttribute (KMPlayer::StringPool::attr_name);
}
KDE_NO_EXPORT void TVInput::setNodeName (const TQString & name) {
Node * p = parentNode ().ptr ();
TQString nm (name);
if (p && p->id == id_node_tv_device) {
int pos = name.find (TQString (" - ") + p->mrl ()->pretty_name);
if (pos > -1)
nm.truncate (pos);
}
pretty_name = nm + TQString (" - ") + pretty_name;
TVNode::setNodeName (nm);
}
//-----------------------------------------------------------------------------
KDE_NO_CDTOR_EXPORT TVDevice::TVDevice (KMPlayer::NodePtr & doc, const TQString & d) : TVNode (doc, d, "device", id_node_tv_device), zombie (false) {
setAttribute ("path", d);
}
KDE_NO_CDTOR_EXPORT TVDevice::TVDevice (KMPlayer::NodePtr & doc)
: TVNode (doc, i18n ("tv device"), "device", id_node_tv_device), zombie (false) {
}
KDE_NO_CDTOR_EXPORT TVDevice::~TVDevice () {
if (device_page)
device_page->deleteLater ();
}
KDE_NO_EXPORT KMPlayer::NodePtr TVDevice::childFromTag (const TQString & tag) {
// kdDebug () << nodeName () << " childFromTag " << tag << endl;
if (tag == TQString::fromLatin1 ("input"))
return new TVInput (m_doc);
return 0L;
}
KDE_NO_EXPORT void TVDevice::closed () {
updateNodeName ();
}
KDE_NO_EXPORT void TVDevice::childDone (KMPlayer::NodePtr) {
finish ();
}
KDE_NO_EXPORT void TVDevice::setNodeName (const TQString & name) {
TVNode::setNodeName (name);
updateNodeName ();
}
KDE_NO_EXPORT void TVDevice::updateNodeName () {
pretty_name = getAttribute (KMPlayer::StringPool::attr_name);
src = getAttribute ("path");
for (KMPlayer::NodePtr c = firstChild (); c; c = c->nextSibling ())
if (c->id == id_node_tv_input) {
TVInput * i = static_cast <TVInput *> (c.ptr ());
i->pretty_name = i->getAttribute (KMPlayer::StringPool::attr_name) +
TQString (" - ") + pretty_name;
}
}
KDE_NO_EXPORT void TVDevice::updateDevicePage () {
if (!device_page)
return;
pretty_name = device_page->name->text ();
setAttribute (KMPlayer::StringPool::attr_name, pretty_name);
setAttribute ("audio", device_page->audiodevice->lineEdit()->text ());
setAttribute ("playback", device_page->noplayback->isChecked() ? "0" : "1");
setAttribute (KMPlayer::StringPool::attr_width, device_page->sizewidth->text ());
setAttribute (KMPlayer::StringPool::attr_height, device_page->sizeheight->text ());
int i = 0;
for (KMPlayer::NodePtr ip = firstChild(); ip; ip=ip->nextSibling(),++i) {
if (ip->id != id_node_tv_input)
continue;
TVInput * input = KMPlayer::convertNode <TVInput> (ip);
bool ok;
if (input->getAttribute ("tuner").toInt (&ok) && ok) {
TQWidget * widget = device_page->inputsTab->page (i);
TQTable * table = static_cast <TQTable *> (TQT_TQWIDGET(widget->child ("PageTVChannels", TQTABLE_OBJECT_NAME_STRING)));
if (table) {
input->clearChildren ();
for (int j = 0; j<table->numRows() && table->item (j, 1); ++j) {
input->appendChild (new TVChannel (m_doc, table->item (j, 0)->text (), table->item (j, 1)->text ().toDouble ()));
}
}
TQComboBox * norms = static_cast <TQComboBox *> (TQT_TQWIDGET(widget->child ("PageTVNorm", TQCOMBOBOX_OBJECT_NAME_STRING)));
if (norms) {
input->setAttribute ("norm", norms->currentText ());
}
}
}
}
//-----------------------------------------------------------------------------
KDE_NO_CDTOR_EXPORT
TVDocument::TVDocument (KMPlayerTVSource * source)
: FileDocument (id_node_tv_document, "tv://", source), m_source (source) {
pretty_name = i18n ("Television");
}
KDE_NO_EXPORT KMPlayer::NodePtr TVDocument::childFromTag (const TQString & tag) {
// kdDebug () << nodeName () << " childFromTag " << tag << endl;
if (tag == TQString::fromLatin1 ("device"))
return new TVDevice (m_doc);
return FileDocument::childFromTag (tag);
}
KDE_NO_EXPORT void TVDocument::childDone (KMPlayer::NodePtr) {
finish ();
}
KDE_NO_EXPORT void TVDocument::defer () {
if (!resolved) {
resolved = true;
readFromFile (locateLocal ("data", "kmplayer/tv.xml"));
}
}
//-----------------------------------------------------------------------------
KDE_NO_CDTOR_EXPORT KMPlayerTVSource::KMPlayerTVSource (KMPlayerApp * a, TQPopupMenu * m)
: KMPlayerMenuSource (i18n ("TV"), a, m, "tvsource"), m_configpage (0L), scanner (0L), config_read (false) {
m_url = "tv://";
m_menu->insertTearOffHandle ();
connect (m_menu, TQT_SIGNAL (aboutToShow ()), this, TQT_SLOT (menuAboutToShow ()));
m_document = new TVDocument (this);
m_player->settings ()->addPage (this);
tree_id = static_cast <KMPlayer::View*>(m_player->view ())->playList ()->addTree (m_document, "tvsource", "tv", KMPlayer::PlayListView::TreeEdit | KMPlayer::PlayListView::Moveable | KMPlayer::PlayListView::Deleteable);
}
KDE_NO_CDTOR_EXPORT KMPlayerTVSource::~KMPlayerTVSource () {
}
KDE_NO_EXPORT void KMPlayerTVSource::activate () {
m_identified = true;
if (m_player->settings ()->showbroadcastbutton)
m_app->view()->controlPanel()->broadcastButton ()->show ();
if (m_cur_tvdevice && !m_current) {
for (KMPlayer::NodePtr i = m_cur_tvdevice->firstChild(); i && !m_current; i=i->nextSibling())
if (i->id == id_node_tv_input) {
TVInput * input = KMPlayer::convertNode <TVInput> (i);
bool ok;
m_cur_tvinput = i;
if (input->getAttribute ("tuner").toInt (&ok) && ok) {
for (KMPlayer::NodePtr c = i->firstChild (); c; c = c->nextSibling ())
if (c->id == id_node_tv_channel) {
m_current = c;
break;
}
} else
m_current = i;
}
} else if (!m_cur_tvdevice)
KMPlayer::Source::reset ();
buildArguments ();
if (m_cur_tvdevice) {
TQString playback = static_cast <KMPlayer::Element *> (m_cur_tvdevice.ptr ())->getAttribute (TQString::fromLatin1 ("playback"));
if (playback.isEmpty () || playback.toInt ())
TQTimer::singleShot (0, m_player, TQT_SLOT (play ()));
}
}
/* TODO: playback by
* ffmpeg -vd /dev/video0 -r 25 -s 768x576 -f rawvideo - |mplayer -nocache -ao arts -rawvideo on:w=768:h=576:fps=25 -quiet -
*/
KDE_NO_EXPORT void KMPlayerTVSource::deactivate () {
if (m_player->view () && !m_app->view ()->controlPanel()->broadcastButton ()->isOn ())
m_app->view ()->controlPanel()->broadcastButton ()->hide ();
reset ();
}
KDE_NO_EXPORT void KMPlayerTVSource::buildMenu () {
m_menu->clear ();
int counter = 0;
for (KMPlayer::NodePtr dp = m_document->firstChild (); dp; dp = dp->nextSibling ())
if (dp->id == id_node_tv_device)
m_menu->insertItem (KMPlayer::convertNode <TVDevice> (dp)->pretty_name, this, TQT_SLOT (menuClicked (int)), 0, counter++);
}
KDE_NO_EXPORT void KMPlayerTVSource::menuAboutToShow () {
readXML ();
}
void KMPlayerTVSource::jump (KMPlayer::NodePtr e) {
if (e->id == id_node_tv_document) {
readXML ();
} else {
m_current = e;
for (; e; e = e->parentNode ()) {
if (e->id == id_node_tv_device) {
m_cur_tvdevice = e;
break;
} else if (e->id == id_node_tv_input)
m_cur_tvinput = e;
}
if (m_player->source () != this)
m_player->setSource (this);
else if (m_player->process ()->playing ()) {
m_back_request = m_current;
m_player->process ()->stop ();
} else
playCurrent ();
}
}
KDE_NO_EXPORT KMPlayer::NodePtr KMPlayerTVSource::root () {
return m_cur_tvinput;
}
KDE_NO_EXPORT void KMPlayerTVSource::buildArguments () {
TVChannel * channel = 0L;
TVInput * input = 0L;
KMPlayer::NodePtr elm = m_current;
if (elm && elm->id == id_node_tv_channel) {
channel = KMPlayer::convertNode <TVChannel> (elm);
elm = elm->parentNode ();
}
if (elm && elm->id == id_node_tv_input)
input = KMPlayer::convertNode <TVInput> (elm);
if (!(channel || (input && input->getAttribute ("tuner").isEmpty ())))
return;
m_cur_tvinput = input;
m_cur_tvdevice = input->parentNode ();
static_cast <KMPlayer::View*>(m_player->view ())->playList ()->updateTree (0, m_cur_tvinput, m_current, true, false);
if (m_cur_tvdevice->id != id_node_tv_device) {
return;
}
TVDevice * tvdevice = KMPlayer::convertNode <TVDevice> (m_cur_tvdevice);
m_identified = true;
m_audiodevice = tvdevice->getAttribute ("audio");
m_videodevice = tvdevice->src;
m_videonorm = input->getAttribute ("norm");
m_tuner = input->getAttribute (KMPlayer::StringPool::attr_name);
TQString xvport = tvdevice->getAttribute ("xvport");
if (!xvport.isEmpty ())
m_xvport = xvport.toInt ();
TQString xvenc = input->getAttribute ("xvenc");
if (!xvenc.isEmpty ())
m_xvencoding = xvenc.toInt ();
TQString command;
command.sprintf ("device=%s:input=%s",
tvdevice->src.ascii (),
input->getAttribute (KMPlayer::StringPool::attr_id).ascii ());
if (channel) {
TQString freq = channel->getAttribute ("frequency");
m_frequency = (int)(1000 * freq.toDouble ());
command += TQString (":freq=%1").arg (freq);
} else
m_frequency = 0;
if (!m_videonorm.isEmpty ())
command += TQString (":norm=%1").arg (m_videonorm);
m_app->setCaption (i18n ("TV: ") + (channel ? channel->mrl ()->pretty_name : input->mrl ()->pretty_name), false);
setDimensions (m_cur_tvdevice,
tvdevice->getAttribute (KMPlayer::StringPool::attr_width).toInt (),
tvdevice->getAttribute (KMPlayer::StringPool::attr_height).toInt ());
m_options.sprintf ("-tv noaudio:driver=%s:%s:width=%d:height=%d -slave -nocache -quiet", tvdriver.ascii (), command.ascii (), width (), height ());
if (m_player->settings ()->mplayerpost090)
m_recordcmd.sprintf ("-tv %s:driver=%s:%s:width=%d:height=%d", m_audiodevice.isEmpty () ? "noaudio" : (TQString ("forceaudio:adevice=") + m_audiodevice).ascii(), tvdriver.ascii (), command.ascii (), width (), height ());
else
m_recordcmd.sprintf ("-tv on:%s:driver=%s:%s:width=%d:height=%d", m_audiodevice.isEmpty () ? "noaudio" : (TQString ("forceaudio:adevice=") + m_audiodevice).ascii(), tvdriver.ascii (), command.ascii (), width (), height ());
}
KDE_NO_EXPORT void KMPlayerTVSource::playCurrent () {
buildArguments ();
if (m_app->broadcasting ())
TQTimer::singleShot (0, m_app->broadcastConfig (), TQT_SLOT (startFeed ()));
else
KMPlayer::Source::playCurrent ();
}
KDE_NO_EXPORT void KMPlayerTVSource::menuClicked (int id) {
KMPlayer::NodePtr elm = m_document->firstChild ();
for (; id > 0; --id, elm = elm->nextSibling ())
;
m_cur_tvdevice = elm;
m_cur_tvinput = elm->firstChild (); // FIXME
m_current = 0L;
m_player->setSource (this);
}
KDE_NO_EXPORT TQString KMPlayerTVSource::filterOptions () {
if (! m_player->settings ()->disableppauto)
return KMPlayer::Source::filterOptions ();
return TQString ("-vf pp=lb");
}
KDE_NO_EXPORT bool KMPlayerTVSource::hasLength () {
return false;
}
KDE_NO_EXPORT bool KMPlayerTVSource::isSeekable () {
return true;
}
KDE_NO_EXPORT TQString KMPlayerTVSource::prettyName () {
TQString name (i18n ("TV"));
//if (m_tvsource)
// name += ' ' + m_tvsource->title;
return name;
}
KDE_NO_EXPORT void KMPlayerTVSource::write (TDEConfig * m_config) {
if (!config_read) return;
m_config->setGroup (strTV);
m_config->writeEntry (strTVDriver, tvdriver);
static_cast <TVDocument *> (m_document.ptr ())->writeToFile
(locateLocal ("data", "kmplayer/tv.xml"));
kdDebug () << "KMPlayerTVSource::write XML" << endl;
}
KDE_NO_EXPORT void KMPlayerTVSource::readXML () {
if (config_read) return;
config_read = true;
kdDebug () << "KMPlayerTVSource::readXML" << endl;
m_document->defer ();
static_cast <KMPlayer::View*>(m_player->view ())->playList ()->updateTree (tree_id, m_document, 0, false, false);
buildMenu ();
sync (false);
}
KDE_NO_EXPORT void KMPlayerTVSource::read (TDEConfig * m_config) {
m_config->setGroup (strTV);
tvdriver = m_config->readEntry (strTVDriver, "v4l");
}
KDE_NO_EXPORT void KMPlayerTVSource::sync (bool fromUI) {
if (!m_configpage) return;
if (m_document && m_document->hasChildNodes ())
m_app->showBroadcastConfig ();
else
m_app->hideBroadcastConfig ();
if (fromUI) {
tvdriver = m_configpage->driver->text ();
for (KMPlayer::NodePtr d=m_document->firstChild();d; d=d->nextSibling())
if (d->id == id_node_tv_device)
static_cast <TVDevice *> (d.ptr ())->updateDevicePage ();
} else {
m_configpage->driver->setText (tvdriver);
for (KMPlayer::NodePtr dp = m_document->firstChild (); dp; dp = dp->nextSibling ())
if (dp->id == id_node_tv_device)
addTVDevicePage (KMPlayer::convertNode <TVDevice> (dp));
}
}
KDE_NO_EXPORT void KMPlayerTVSource::prefLocation (TQString & item, TQString & icon, TQString & tab) {
item = i18n ("Source");
icon = TQString ("source");
tab = i18n ("TV");
}
KDE_NO_EXPORT TQFrame * KMPlayerTVSource::prefPage (TQWidget * parent) {
if (!m_configpage) {
m_configpage = new KMPlayerPrefSourcePageTV (parent, this);
scanner = new TVDeviceScannerSource (this);
connect (m_configpage->scan, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotScan()));
}
return m_configpage;
}
static bool hasTVDevice (KMPlayer::NodePtr doc, const TQString & devstr) {
for (KMPlayer::NodePtr e = doc->firstChild (); e; e = e->nextSibling ())
if (e->id == id_node_tv_device &&
KMPlayer::convertNode <TVDevice> (e)->src == devstr)
return true;
return false;
}
KDE_NO_EXPORT void KMPlayerTVSource::slotScan () {
TQString devstr = m_configpage->device->lineEdit()->text ();
if (!hasTVDevice(m_document, devstr)) {
scanner->scan (devstr, m_configpage->driver->text());
connect (scanner, TQT_SIGNAL (scanFinished (TVDevice *)),
this, TQT_SLOT (slotScanFinished (TVDevice *)));
} else
KMessageBox::error (m_configpage, i18n ("Device already present."),
i18n ("Error"));
}
KDE_NO_EXPORT void KMPlayerTVSource::slotScanFinished (TVDevice * tvdevice) {
disconnect (scanner, TQT_SIGNAL (scanFinished (TVDevice *)),
this, TQT_SLOT (slotScanFinished (TVDevice *)));
if (tvdevice) {
tvdevice->zombie = false;
addTVDevicePage (tvdevice, true);
} else
KMessageBox::error(m_configpage,i18n("No device found."),i18n("Error"));
}
KDE_NO_EXPORT void KMPlayerTVSource::addTVDevicePage(TVDevice *dev, bool show) {
if (dev->device_page)
dev->device_page->deleteLater ();
dev->device_page = new TVDevicePage (m_configpage->notebook, dev);
m_configpage->notebook->insertTab (dev->device_page, dev->pretty_name);
connect (dev->device_page, TQT_SIGNAL (deleted (TVDevicePage *)),
this, TQT_SLOT (slotDeviceDeleted (TVDevicePage *)));
if (show)
m_configpage->notebook->setCurrentPage (m_configpage->notebook->count ()-1);
}
KDE_NO_EXPORT void KMPlayerTVSource::slotDeviceDeleted (TVDevicePage *devpage) {
m_document->removeChild (devpage->device_doc);
m_configpage->notebook->setCurrentPage (0);
}
//-----------------------------------------------------------------------------
KDE_NO_CDTOR_EXPORT TVDeviceScannerSource::TVDeviceScannerSource (KMPlayerTVSource * src)
: KMPlayer::Source (i18n ("TVScanner"), src->player (), "tvscanner"), m_tvsource (src), m_tvdevice (0L) {
}
KDE_NO_EXPORT void TVDeviceScannerSource::init () {
}
KDE_NO_EXPORT bool TVDeviceScannerSource::processOutput (const TQString & line) {
if (m_nameRegExp.search (line) > -1) {
m_tvdevice->pretty_name = m_nameRegExp.cap (1);
m_tvdevice->setAttribute(KMPlayer::StringPool::attr_name,m_tvdevice->pretty_name);
kdDebug() << "Name " << m_tvdevice->pretty_name << endl;
} else if (m_sizesRegExp.search (line) > -1) {
m_tvdevice->setAttribute (KMPlayer::StringPool::attr_width,
m_sizesRegExp.cap(1));
m_tvdevice->setAttribute (KMPlayer::StringPool::attr_height,
m_sizesRegExp.cap(2));
m_tvdevice->setAttribute ("minwidth", m_sizesRegExp.cap (1));
m_tvdevice->setAttribute ("minheight", m_sizesRegExp.cap (2));
m_tvdevice->setAttribute ("maxwidth", m_sizesRegExp.cap (3));
m_tvdevice->setAttribute ("maxheight", m_sizesRegExp.cap (4));
} else if (m_inputRegExp.search (line) > -1) {
KMPlayer::NodePtr doc = m_tvsource->document ();
TVInput * input = new TVInput (doc, m_inputRegExp.cap (2).stripWhiteSpace (),
m_inputRegExp.cap (1).toInt ());
if (m_inputRegExp.cap (3).toInt () == 1)
input->setAttribute ("tuner", "1");
m_tvdevice->appendChild (input);
kdDebug() << "Input " << input->mrl ()->pretty_name << endl;
} else
return false;
return true;
}
KDE_NO_EXPORT TQString TVDeviceScannerSource::filterOptions () {
return TQString ("");
}
KDE_NO_EXPORT bool TVDeviceScannerSource::hasLength () {
return false;
}
KDE_NO_EXPORT bool TVDeviceScannerSource::isSeekable () {
return false;
}
KDE_NO_EXPORT bool TVDeviceScannerSource::scan (const TQString & dev, const TQString & dri) {
if (m_tvdevice)
return false;
setURL (KURL ("tv://"));
KMPlayer::NodePtr doc = m_tvsource->document ();
m_tvdevice = new TVDevice (doc, dev);
m_tvsource->document ()->appendChild (m_tvdevice);
m_tvdevice->zombie = true; // not for real yet
m_driver = dri;
m_old_source = m_tvsource->player ()->source ();
m_tvsource->player ()->setSource (this);
m_identified = true;
play ();
return true;
}
KDE_NO_EXPORT void TVDeviceScannerSource::activate () {
m_nameRegExp.setPattern ("Selected device:\\s*([^\\s].*)");
m_sizesRegExp.setPattern ("Supported sizes:\\s*([0-9]+)x([0-9]+) => ([0-9]+)x([0-9]+)");
m_inputRegExp.setPattern ("\\s*([0-9]+):\\s*([^:]+):[^\\(]*\\(tuner:([01]),\\s*norm:([^\\)]+)\\)");
}
KDE_NO_EXPORT void TVDeviceScannerSource::deactivate () {
kdDebug () << "TVDeviceScannerSource::deactivate" << endl;
if (m_tvdevice) {
if (m_tvdevice->parentNode ())
m_tvdevice->parentNode ()->removeChild (m_tvdevice);
m_tvdevice = 0L;
emit scanFinished (m_tvdevice);
}
}
KDE_NO_EXPORT void TVDeviceScannerSource::play () {
if (!m_tvdevice)
return;
TQString args;
args.sprintf ("tv:// -tv driver=%s:device=%s -identify -frames 0", m_driver.ascii (), m_tvdevice->src.ascii ());
m_tvsource->player ()->stop ();
m_tvsource->player ()->process ()->initProcess (m_player->settings ()->defaultView ()->viewer ());
KMPlayer::Process *proc = m_tvsource->player ()->players () ["mplayer"];
proc->setSource (this);
if (!static_cast <KMPlayer::MPlayer *> (proc)->run (args.ascii()))
deactivate ();
}
KDE_NO_EXPORT void TVDeviceScannerSource::stateChange (KMPlayer::Process * p, KMPlayer::Process::State os, KMPlayer::Process::State ns) {
if (m_tvdevice && // can be deactivated
ns == KMPlayer::Process::Ready && os > KMPlayer::Process::Ready) {
TVDevice * dev = 0L;
kdDebug () << "scanning done " << m_tvdevice->hasChildNodes () << endl;
if (!m_tvdevice->hasChildNodes ())
m_tvsource->document ()->removeChild (m_tvdevice);
else
dev = m_tvdevice;
m_tvdevice = 0L;
m_player->setSource (m_old_source);
emit scanFinished (dev);
}
KMPlayer::Source::stateChange (p, os, ns);
}
#include "kmplayertvsource.moc"