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.
738 lines
30 KiB
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 *tqparent, KMPlayer::NodePtr dev)
|
|
: TQFrame (tqparent, "PageTVDevice"), device_doc (dev) {
|
|
TVDevice * device = KMPlayer::convertNode <TVDevice> (device_doc);
|
|
TQVBoxLayout *tqlayout = new TQVBoxLayout (this, 5, 2);
|
|
TQLabel * deviceLabel = new TQLabel (i18n ("Video device:") + device->src, this, 0);
|
|
tqlayout->addWidget (deviceLabel);
|
|
TQGridLayout *gridtqlayout = new TQGridLayout (tqlayout, 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 *tabtqlayout = new TQHBoxLayout (widget, 5, 2);
|
|
if (!input->getAttribute ("tuner").isEmpty ()) {
|
|
TQHBoxLayout *horztqlayout = new TQHBoxLayout ();
|
|
TQVBoxLayout *verttqlayout = new TQVBoxLayout ();
|
|
horztqlayout->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"));
|
|
horztqlayout->addWidget (norms);
|
|
verttqlayout->addLayout (horztqlayout);
|
|
verttqlayout->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);
|
|
tabtqlayout->addWidget (table);
|
|
tabtqlayout->addLayout (verttqlayout);
|
|
}
|
|
inputsTab->addTab (widget, input->mrl ()->pretty_name);
|
|
}
|
|
TQPushButton * delButton = new TQPushButton (i18n ("Delete"), this);
|
|
connect (delButton, TQT_SIGNAL (clicked ()), this, TQT_SLOT (slotDelete ()));
|
|
gridtqlayout->addWidget (audioLabel, 0, 0);
|
|
gridtqlayout->addMultiCellWidget (audiodevice, 0, 0, 1, 3);
|
|
gridtqlayout->addWidget (nameLabel, 1, 0);
|
|
gridtqlayout->addMultiCellWidget (name, 1, 1, 1, 3);
|
|
gridtqlayout->addWidget (sizewidthLabel, 2, 0);
|
|
gridtqlayout->addWidget (sizewidth, 2, 1);
|
|
gridtqlayout->addWidget (sizeheightLabel, 2, 2);
|
|
gridtqlayout->addWidget (sizeheight, 2, 3);
|
|
tqlayout->addWidget (inputsTab);
|
|
tqlayout->addSpacing (5);
|
|
tqlayout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Minimum, TQSizePolicy::Minimum));
|
|
TQHBoxLayout *buttontqlayout = new TQHBoxLayout ();
|
|
buttontqlayout->addWidget (noplayback);
|
|
buttontqlayout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
|
|
buttontqlayout->addWidget (delButton);
|
|
tqlayout->addLayout (buttontqlayout);
|
|
}
|
|
|
|
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 *tqparent, KMPlayerTVSource * tvsource)
|
|
: TQFrame (tqparent), m_tvsource (tvsource) {
|
|
TQVBoxLayout * maintqlayout = new TQVBoxLayout (this, 5);
|
|
notebook = new TQTabWidget (this);
|
|
notebook->setTabPosition (TQTabWidget::Bottom);
|
|
maintqlayout->addWidget (notebook);
|
|
TQWidget * general = new TQWidget (notebook);
|
|
TQVBoxLayout *tqlayout = new TQVBoxLayout (general);
|
|
TQGridLayout *gridtqlayout = new TQGridLayout (tqlayout, 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);
|
|
gridtqlayout->addWidget (driverLabel, 0, 0);
|
|
gridtqlayout->addWidget (driver, 0, 1);
|
|
gridtqlayout->addWidget (deviceLabel, 1, 0);
|
|
gridtqlayout->addWidget (device, 1, 1);
|
|
TQHBoxLayout *buttontqlayout = new TQHBoxLayout ();
|
|
buttontqlayout->addItem (new TQSpacerItem (0, 0, TQSizePolicy::Minimum, TQSizePolicy::Minimum));
|
|
buttontqlayout->addWidget (scan);
|
|
tqlayout->addLayout (buttontqlayout);
|
|
tqlayout->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::tqfromLatin1 ("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::tqfromLatin1 ("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::tqfromLatin1 ("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::tqfromLatin1 ("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 (KConfig * 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 (KConfig * 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 * tqparent) {
|
|
if (!m_configpage) {
|
|
m_configpage = new KMPlayerPrefSourcePageTV (tqparent, 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"
|