File indexing completed on 2024-04-21 15:38:15
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., 59 temple place - suite 330, 0017 boston, ma 02111-1307, usa. 0018 */ 0019 #include <algorithm> 0020 0021 #include <qlayout.h> 0022 #include <qlabel.h> 0023 #include <qpushbutton.h> 0024 #include <qtable.h> 0025 #include <qstringlist.h> 0026 #include <qcombobox.h> 0027 #include <qlistbox.h> 0028 #include <qlineedit.h> 0029 #include <qwhatsthis.h> 0030 #include <qtabwidget.h> 0031 #include <qcursor.h> 0032 #include <qdir.h> 0033 #include <qfile.h> 0034 #include <qtimer.h> 0035 0036 #include <klocalizedstring.h> 0037 #include <kdebug.h> 0038 #include <kled.h> 0039 #include <kconfig.h> 0040 #include <kprocess.h> 0041 #include <kprocctrl.h> 0042 #include <kmessagebox.h> 0043 0044 #include "kmplayerbroadcast.h" 0045 #include "kmplayerprocess.h" 0046 #include "kmplayerview.h" 0047 #include "kmplayerpartbase.h" 0048 0049 static const char * strBroadcast = "Broadcast"; 0050 static const char * strBindAddress = "Bind Address"; 0051 static const char * strFFServerPort = "FFServer Port"; 0052 static const char * strMaxClients = "Maximum Connections"; 0053 static const char * strMaxBandwidth = "Maximum Bandwidth"; 0054 static const char * strFeedFile = "Feed File"; 0055 static const char * strFeedFileSize = "Feed File Size"; 0056 //static const char * strFFServerSetting = "FFServer Setting"; 0057 static const char * strFFServerCustomSetting = "Custom Setting"; 0058 static const char * strFFServerProfiles = "Profiles"; 0059 0060 0061 KDE_NO_CDTOR_EXPORT FFServerSetting::FFServerSetting (int i, const QString & n, const QString & f, const QString & ac, int abr, int asr, const QString & vc, int vbr, int q, int fr, int gs, int w, int h) 0062 : index (i), name (n), format (f), audiocodec (ac), 0063 audiobitrate (abr > 0 ? QString::number (abr) : QString ()), 0064 audiosamplerate (asr > 0 ? QString::number (asr) : QString ()), 0065 videocodec (vc), 0066 videobitrate (vbr > 0 ? QString::number (vbr) : QString ()), 0067 quality (q > 0 ? QString::number (q) : QString ()), 0068 framerate (fr > 0 ? QString::number (fr) : QString ()), 0069 gopsize (gs > 0 ? QString::number (gs) : QString ()), 0070 width (w > 0 ? QString::number (w) : QString ()), 0071 height (h > 0 ? QString::number (h) : QString ()) {} 0072 0073 KDE_NO_EXPORT FFServerSetting & FFServerSetting::operator = (const FFServerSetting & fs) { 0074 format = fs.format; 0075 audiocodec = fs.audiocodec; 0076 audiobitrate = fs.audiobitrate; 0077 audiosamplerate = fs.audiosamplerate; 0078 videocodec = fs.videocodec; 0079 videobitrate = fs.videobitrate; 0080 quality = fs.quality; 0081 framerate = fs.framerate; 0082 gopsize = fs.gopsize; 0083 width = fs.width; 0084 height = fs.height; 0085 return *this; 0086 } 0087 0088 KDE_NO_EXPORT FFServerSetting & FFServerSetting::operator = (const QStringList & sl) { 0089 if (sl.count () < 11) { 0090 return *this; 0091 } 0092 QStringList::const_iterator it = sl.begin (); 0093 format = *it++; 0094 audiocodec = *it++; 0095 audiobitrate = *it++; 0096 audiosamplerate = *it++; 0097 videocodec = *it++; 0098 videobitrate = *it++; 0099 quality = *it++; 0100 framerate = *it++; 0101 gopsize = *it++; 0102 width = *it++; 0103 height = *it++; 0104 acl.clear (); 0105 QStringList::const_iterator end( sl.end() ); 0106 for (; it != end; ++it) 0107 acl.push_back (*it); 0108 return *this; 0109 } 0110 0111 KDE_NO_EXPORT QString & FFServerSetting::ffconfig (QString & buf) { 0112 QString nl ("\n"); 0113 buf = QString ("Format ") + format + nl; 0114 if (!audiocodec.isEmpty ()) 0115 buf += QString ("AudioCodec ") + audiocodec + nl; 0116 if (!audiobitrate.isEmpty ()) 0117 buf += QString ("AudioBitRate ") + audiobitrate + nl; 0118 if (!audiosamplerate.isEmpty () > 0) 0119 buf += QString ("AudioSampleRate ") + audiosamplerate + nl; 0120 if (!videocodec.isEmpty ()) 0121 buf += QString ("VideoCodec ") + videocodec + nl; 0122 if (!videobitrate.isEmpty ()) 0123 buf += QString ("VideoBitRate ") + videobitrate + nl; 0124 if (!quality.isEmpty ()) 0125 buf += QString ("VideoQMin ") + quality + nl; 0126 if (!framerate.isEmpty ()) 0127 buf += QString ("VideoFrameRate ") + framerate + nl; 0128 if (!gopsize.isEmpty ()) 0129 buf += QString ("VideoGopSize ") + gopsize + nl; 0130 if (!width.isEmpty () && !height.isEmpty ()) 0131 buf += QString ("VideoSize ") + width + QString ("x") + height + nl; 0132 return buf; 0133 } 0134 0135 KDE_NO_EXPORT const QStringList FFServerSetting::list () { 0136 QStringList sl; 0137 sl.push_back (format); 0138 sl.push_back (audiocodec); 0139 sl.push_back (audiobitrate); 0140 sl.push_back (audiosamplerate); 0141 sl.push_back (videocodec); 0142 sl.push_back (videobitrate); 0143 sl.push_back (quality); 0144 sl.push_back (framerate); 0145 sl.push_back (gopsize); 0146 sl.push_back (width); 0147 sl.push_back (height); 0148 QStringList::const_iterator it = acl.begin (); 0149 QStringList::const_iterator end( acl.end () ); 0150 for (; it != end; ++it) 0151 sl.push_back (*it); 0152 return sl; 0153 } 0154 0155 //----------------------------------------------------------------------------- 0156 0157 KDE_NO_CDTOR_EXPORT KMPlayerPrefBroadcastPage::KMPlayerPrefBroadcastPage (QWidget *parent) : QFrame (parent) { 0158 QVBoxLayout *layout = new QVBoxLayout (this, 5); 0159 QGridLayout *gridlayout = new QGridLayout (layout, 6, 2, 2); 0160 QLabel *label = new QLabel (i18n ("Bind address:"), this); 0161 bindaddress = new QLineEdit ("", this); 0162 QWhatsThis::add (bindaddress, i18n ("If you have multiple network devices, you can limit access")); 0163 gridlayout->addWidget (label, 0, 0); 0164 gridlayout->addWidget (bindaddress, 0, 1); 0165 label = new QLabel (i18n ("Listen port:"), this); 0166 port = new QLineEdit ("", this); 0167 gridlayout->addWidget (label, 1, 0); 0168 gridlayout->addWidget (port, 1, 1); 0169 label = new QLabel (i18n ("Maximum connections:"), this); 0170 maxclients = new QLineEdit ("", this); 0171 gridlayout->addWidget (label, 2, 0); 0172 gridlayout->addWidget (maxclients, 2, 1); 0173 label = new QLabel (i18n ("Maximum bandwidth (kbit):"), this); 0174 maxbandwidth = new QLineEdit ("", this); 0175 gridlayout->addWidget (label, 3, 0); 0176 gridlayout->addWidget (maxbandwidth, 3, 1); 0177 label = new QLabel (i18n ("Temporary feed file:"), this); 0178 feedfile = new QLineEdit ("", this); 0179 gridlayout->addWidget (label, 4, 0); 0180 gridlayout->addWidget (feedfile, 4, 1); 0181 label = new QLabel (i18n ("Feed file size (kB):"), this); 0182 feedfilesize = new QLineEdit ("", this); 0183 gridlayout->addWidget (label, 5, 0); 0184 gridlayout->addWidget (feedfilesize, 5, 1); 0185 layout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); 0186 } 0187 0188 //----------------------------------------------------------------------------- 0189 0190 #undef ADDPROPERTY 0191 #define ADDPROPERTY(label,qedit,gridlayout,row,parent) \ 0192 qedit = new QLineEdit ("", parent); \ 0193 gridlayout->addWidget (new QLabel (qedit, label, parent), row, 0); \ 0194 gridlayout->addWidget (qedit, row, 1); 0195 0196 KDE_NO_CDTOR_EXPORT KMPlayerPrefBroadcastFormatPage::KMPlayerPrefBroadcastFormatPage (QWidget *parent, FFServerSettingList & ffs) : QFrame (parent, "BroadcastPage"), profiles (ffs) 0197 { 0198 QHBoxLayout *layout = new QHBoxLayout (this, 5); 0199 QGridLayout *formatlayout = new QGridLayout (11, 2, 2); 0200 formatlayout->setAlignment (Qt::AlignTop); 0201 QVBoxLayout *leftlayout = new QVBoxLayout (15); 0202 QHBoxLayout *ledlayout = new QHBoxLayout (5); 0203 format = new QComboBox (this); 0204 QLabel * label = new QLabel (format, i18n ("Format:"), this); 0205 format->clear (); 0206 format->insertItem (QString ("asf")); 0207 format->insertItem (QString ("avi")); 0208 format->insertItem (QString ("mpjpeg")); 0209 format->insertItem (QString ("mpeg")); 0210 format->insertItem (QString ("rm")); 0211 format->insertItem (QString ("swf")); 0212 QWhatsThis::add (format, i18n ("Only avi, mpeg and rm work for mplayer playback")); 0213 formatlayout->addWidget (label, 0, 0); 0214 formatlayout->addWidget (format, 0, 1); 0215 ADDPROPERTY (i18n ("Audio codec:"), audiocodec, formatlayout, 1, this); 0216 ADDPROPERTY (i18n ("Audio bit rate (kbit):"), audiobitrate, formatlayout, 2, this); 0217 ADDPROPERTY (i18n ("Audio sample rate (Hz):"), audiosamplerate, formatlayout, 3, this); 0218 ADDPROPERTY (i18n ("Video codec:"), videocodec, formatlayout, 4, this); 0219 ADDPROPERTY (i18n ("Video bit rate (kbit):"), videobitrate, formatlayout, 5, this); 0220 ADDPROPERTY (i18n ("Quality (1-31):"), quality, formatlayout, 6, this); 0221 ADDPROPERTY (i18n ("Frame rate (Hz):"), framerate, formatlayout, 7, this); 0222 ADDPROPERTY (i18n ("Gop size:"), gopsize, formatlayout, 8, this); 0223 ADDPROPERTY (i18n ("Width (pixels):"), moviewidth, formatlayout, 9, this); 0224 ADDPROPERTY (i18n ("Height (pixels):"), movieheight, formatlayout, 10, this); 0225 label = new QLabel (i18n ("Allow access from:"), this); 0226 accesslist = new QTable (40, 1, this); 0227 accesslist->verticalHeader ()->hide (); 0228 accesslist->setLeftMargin (0); 0229 accesslist->setColumnWidth (0, 250); 0230 QWhatsThis::add (accesslist, i18n ("'Single IP' or 'start-IP end-IP' for IP ranges")); 0231 QHeader *header = accesslist->horizontalHeader (); 0232 header->setLabel (0, i18n ("Host/IP or IP Range")); 0233 QFrame *profileframe = new QFrame (this); 0234 QGridLayout *profileslayout = new QGridLayout (profileframe, 5, 2, 2); 0235 profile = new QLineEdit ("", profileframe); 0236 connect (profile, SIGNAL(textChanged (const QString &)), 0237 this, SLOT (slotTextChanged (const QString &))); 0238 profilelist = new QListBox (profileframe); 0239 for (int i = 0; i < (int) profiles.size (); i++) 0240 profilelist->insertItem (profiles[i]->name, i); 0241 connect (profilelist, SIGNAL (selected (int)), 0242 this, SLOT (slotIndexChanged (int))); 0243 connect (profilelist, SIGNAL (highlighted (int)), 0244 this, SLOT (slotItemHighlighted (int))); 0245 load = new QPushButton (i18n ("Load"), profileframe); 0246 save = new QPushButton (i18n ("Save"), profileframe); 0247 del = new QPushButton (i18n ("Delete"), profileframe); 0248 load->setEnabled (false); 0249 save->setEnabled (false); 0250 del->setEnabled (false); 0251 connect (load, SIGNAL (clicked ()), this, SLOT (slotLoad ())); 0252 connect (save, SIGNAL (clicked ()), this, SLOT (slotSave ())); 0253 connect (del, SIGNAL (clicked ()), this, SLOT (slotDelete ())); 0254 profileslayout->addWidget (profile, 0, 0); 0255 #if (QT_VERSION < 0x030200) 0256 profileslayout->addRowSpacing (4, 60); 0257 #else 0258 profileslayout->setRowSpacing (4, 60); 0259 #endif 0260 profileslayout->addMultiCellWidget (profilelist, 1, 4, 0, 0); 0261 profileslayout->addWidget (load, 1, 1); 0262 profileslayout->addWidget (save, 2, 1); 0263 profileslayout->addWidget (del, 3, 1); 0264 leftlayout->addWidget (profileframe); 0265 startbutton = new QPushButton (i18n ("Start"), this); 0266 serverled = new KLed (Qt::green, KLed::Off, KLed::Raised, KLed::Circular, this); 0267 feedled = new KLed (Qt::green, KLed::Off, KLed::Raised, KLed::Circular, this); 0268 ledlayout->addWidget (startbutton); 0269 ledlayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); 0270 ledlayout->addWidget (serverled); 0271 ledlayout->addWidget (feedled); 0272 leftlayout->addLayout (ledlayout); 0273 QFrame * line = new QFrame (this); 0274 line->setFrameShape (QFrame::HLine); 0275 leftlayout->addWidget (line); 0276 leftlayout->addWidget (label); 0277 leftlayout->addWidget (accesslist); 0278 leftlayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); 0279 layout->addLayout (leftlayout); 0280 line = new QFrame (this); 0281 line->setFrameShape (QFrame::VLine); 0282 layout->addWidget (line); 0283 layout->addLayout (formatlayout); 0284 layout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); 0285 } 0286 0287 #undef ADDPROPERTY 0288 0289 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::setSettings (const FFServerSetting & fs) { 0290 if (!fs.format.isEmpty ()) 0291 format->setCurrentText (fs.format); 0292 audiocodec->setText (fs.audiocodec); 0293 audiobitrate->setText (fs.audiobitrate); 0294 audiosamplerate->setText (fs.audiosamplerate); 0295 videocodec->setText (fs.videocodec); 0296 videobitrate->setText (fs.videobitrate); 0297 quality->setText (fs.quality); 0298 framerate->setText (fs.framerate); 0299 gopsize->setText (fs.gopsize); 0300 moviewidth->setText (fs.width); 0301 movieheight->setText (fs.height); 0302 accesslist->setNumRows (0); 0303 accesslist->setNumRows (50); 0304 QStringList::const_iterator it = fs.acl.begin (); 0305 QStringList::const_iterator end( fs.acl.end () ); 0306 for (int i = 0; it != end; ++i, ++it) 0307 accesslist->setItem (i, 0, new QTableItem (accesslist, QTableItem::Always, *it)); 0308 } 0309 0310 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::getSettings (FFServerSetting & fs) { 0311 fs.format = format->currentText (); 0312 fs.audiocodec = audiocodec->text (); 0313 fs.audiobitrate = audiobitrate->text (); 0314 fs.audiosamplerate = audiosamplerate->text (); 0315 fs.videocodec = videocodec->text (); 0316 fs.videobitrate = videobitrate->text (); 0317 fs.quality = quality->text (); 0318 fs.framerate = framerate->text (); 0319 fs.gopsize = gopsize->text (); 0320 fs.width = moviewidth->text (); 0321 fs.height = movieheight->text (); 0322 fs.acl.clear (); 0323 for (int i = 0; i < accesslist->numRows (); ++i) { 0324 if (accesslist->item (i, 0) && !accesslist->item (i, 0)->text ().isEmpty ()) 0325 fs.acl.push_back (accesslist->item (i, 0)->text ()); 0326 } 0327 } 0328 0329 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::slotIndexChanged (int index) { 0330 slotItemHighlighted (index); 0331 if (index >= 0 && index < (int) profiles.size ()) 0332 setSettings (*profiles[index]); 0333 } 0334 0335 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::slotTextChanged (const QString & txt) { 0336 save->setEnabled (txt.size ()); 0337 } 0338 0339 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::slotItemHighlighted (int index) { 0340 if (index < 0 || index >= (int) profiles.size ()) { 0341 load->setEnabled (false); 0342 del->setEnabled (false); 0343 } else { 0344 profile->setText (profiles[profilelist->currentItem ()]->name); 0345 load->setEnabled (true); 0346 del->setEnabled (true); 0347 slotTextChanged (profilelist->currentText ()); 0348 } 0349 } 0350 0351 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::slotSave () { 0352 for (int i = 0; i < (int) profiles.size (); ++i) 0353 if (profiles[i]->name == profile->text ()) { 0354 getSettings (*profiles[i]); 0355 return; 0356 } 0357 FFServerSetting * fs = new FFServerSetting; 0358 fs->name = profile->text (); 0359 getSettings (*fs); 0360 profiles.push_back (fs); 0361 profilelist->insertItem (fs->name); 0362 } 0363 0364 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::slotLoad () { 0365 setSettings (*profiles[profilelist->currentItem ()]); 0366 } 0367 0368 KDE_NO_EXPORT void KMPlayerPrefBroadcastFormatPage::slotDelete () { 0369 FFServerSettingList::iterator it = profiles.begin(); 0370 for (int i = 0; i < profilelist->currentItem (); i++) 0371 ++it; 0372 delete *it; 0373 profiles.erase (it); 0374 profilelist->removeItem (profilelist->currentItem ()); 0375 load->setEnabled (false); 0376 del->setEnabled (false); 0377 } 0378 0379 //----------------------------------------------------------------------------- 0380 0381 static bool stopProcess (KProcess * process, const char * cmd = 0L) { 0382 if (!process || !process->isRunning ()) return true; 0383 do { 0384 if (cmd) 0385 process->writeStdin (cmd, strlen (cmd)); 0386 KProcessController::theKProcessController->waitForProcessExit (1); 0387 if (!process->isRunning ()) 0388 break; 0389 process->kill (SIGINT); 0390 KProcessController::theKProcessController->waitForProcessExit (3); 0391 if (!process->isRunning ()) 0392 break; 0393 process->kill (SIGTERM); 0394 KProcessController::theKProcessController->waitForProcessExit (1); 0395 if (!process->isRunning ()) 0396 break; 0397 process->kill (SIGKILL); 0398 KProcessController::theKProcessController->waitForProcessExit (1); 0399 if (process->isRunning ()) { 0400 return false; // give up 0401 } 0402 } while (false); 0403 return true; 0404 } 0405 0406 0407 KDE_NO_CDTOR_EXPORT KMPlayerBroadcastConfig::KMPlayerBroadcastConfig (KMPlayer::PartBase * player, KMPlayerFFServerConfig * fsc) 0408 : m_player (player), 0409 m_ffserverconfig (fsc), 0410 m_ffmpeg_process (0L), 0411 m_ffserver_process (0L), 0412 m_endserver (true) { 0413 } 0414 0415 KDE_NO_CDTOR_EXPORT KMPlayerBroadcastConfig::~KMPlayerBroadcastConfig () { 0416 stopServer (); 0417 } 0418 0419 KDE_NO_EXPORT void KMPlayerBroadcastConfig::write (KConfig * config) { 0420 config->setGroup (strBroadcast); 0421 config->writeEntry (strFFServerCustomSetting, ffserversettings.list (), ';'); 0422 QStringList sl; 0423 for (int i = 0; i < (int) ffserversettingprofiles.size (); i++) { 0424 sl.push_back (ffserversettingprofiles[i]->name); 0425 config->writeEntry (QString ("Profile_") + ffserversettingprofiles[i]->name, ffserversettingprofiles[i]->list(), ';'); 0426 } 0427 config->writeEntry (strFFServerProfiles, sl, ';'); 0428 } 0429 0430 KDE_NO_EXPORT void KMPlayerBroadcastConfig::read (KConfig * config) { 0431 std::for_each (ffserversettingprofiles.begin (), ffserversettingprofiles.end (), KMPlayer::Deleter<FFServerSetting>()); 0432 ffserversettingprofiles.clear (); 0433 config->setGroup (strBroadcast); 0434 ffserversettings = config->readListEntry (strFFServerCustomSetting, ';'); 0435 QStringList profiles = config->readListEntry (strFFServerProfiles, ';'); 0436 QStringList::iterator pr_it = profiles.begin (); 0437 QStringList::iterator pr_end( profiles.end () ); 0438 for (; pr_it != pr_end; ++pr_it) { 0439 QStringList sl = config->readListEntry (QString ("Profile_") + *pr_it, ';'); 0440 if (sl.size () > 10) { 0441 FFServerSetting * ffs = new FFServerSetting (sl); 0442 ffs->name = *pr_it; 0443 ffserversettingprofiles.push_back (ffs); 0444 } 0445 } 0446 } 0447 0448 KDE_NO_EXPORT void KMPlayerBroadcastConfig::sync (bool fromUI) { 0449 if (fromUI) { 0450 m_configpage->getSettings(ffserversettings); 0451 } else { 0452 m_configpage->setSettings (ffserversettings); 0453 m_configpage->profile->setText (QString ()); 0454 } 0455 } 0456 0457 KDE_NO_EXPORT void KMPlayerBroadcastConfig::prefLocation (QString & item, QString & icon, QString & tab) { 0458 item = i18n ("Broadcasting"); 0459 icon = QString ("share"); 0460 tab = i18n ("Profiles"); 0461 } 0462 0463 QFrame * KMPlayerBroadcastConfig::prefPage (QWidget * parent) { 0464 if (!m_configpage) { 0465 m_configpage = new KMPlayerPrefBroadcastFormatPage (parent, ffserversettingprofiles); 0466 connect (m_configpage->startbutton, SIGNAL (clicked ()), this, SLOT (startServer ())); 0467 connect (m_player, SIGNAL (sourceChanged (KMPlayer::Source *, KMPlayer::Source *)), this, SLOT (sourceChanged (KMPlayer::Source *,KMPlayer::Source *))); 0468 m_configpage->startbutton->setEnabled 0469 (!m_player->source ()->videoDevice ().isEmpty ()); 0470 } 0471 return m_configpage; 0472 } 0473 0474 KDE_NO_EXPORT bool KMPlayerBroadcastConfig::broadcasting () const { 0475 return m_ffserver_process && m_ffserver_process->isRunning (); 0476 } 0477 #include <kglobal.h> 0478 #include <kstandarddirs.h> 0479 0480 static const char ffserverconf[] = 0481 "Port %d\nBindAddress %s\nMaxClients %d\nMaxBandwidth %d\n" 0482 "CustomLog -\nNoDaemon\n" 0483 "<Feed kmplayer.ffm>\nFile %s\nFileMaxSize %dK\nACL allow 127.0.0.1\n</Feed>\n" 0484 "<Stream video.%s>\nFeed kmplayer.ffm\n%s\n%s%s\n</Stream>\n" 0485 "<Stream stat.html>\nFormat status\nACL allow localhost\n</Stream>\n"; 0486 0487 KDE_NO_EXPORT void KMPlayerBroadcastConfig::startServer () { 0488 if (broadcasting ()) { 0489 stopServer (); 0490 return; 0491 } 0492 m_configpage->setCursor (QCursor (Qt::WaitCursor)); 0493 m_ffserver_process = new KProcess; 0494 m_ffserver_process->setUseShell (true); 0495 connect (m_ffserver_process, SIGNAL (processExited (KProcess *)), 0496 this, SLOT (processStopped (KProcess *))); 0497 QString conffile = KStandardDirs::locateLocal ("data", "kmplayer/ffserver.conf"); 0498 const char * noaudio = m_player->source ()->audioDevice ().isEmpty () ? "NoAudio" : ""; 0499 FFServerSetting ffs; 0500 m_configpage->getSettings (ffs); 0501 QString acl; 0502 QStringList::iterator it = ffs.acl.begin (); 0503 QStringList::iterator end( ffs.acl.end () ); 0504 for (; it != end; ++it) 0505 acl += QString ("ACL allow ") + *it + QString ("\n"); 0506 unlink (m_ffserverconfig->feedfile.ascii ()); 0507 QFile qfile (conffile); 0508 qfile.open (IO_WriteOnly); 0509 QString configdata; 0510 QString buf; 0511 configdata.sprintf (ffserverconf, m_ffserverconfig->ffserverport, m_ffserverconfig->bindaddress.ascii (), m_ffserverconfig->maxclients, m_ffserverconfig->maxbandwidth, m_ffserverconfig->feedfile.ascii (), m_ffserverconfig->feedfilesize, ffs.format.ascii (), acl.ascii (), ffs.ffconfig (buf).ascii (), noaudio); 0512 qfile.writeBlock (configdata.ascii (), configdata.size ()); 0513 qfile.close (); 0514 kdDebug () << configdata << endl; 0515 kdDebug () << "ffserver -f " << conffile << endl; 0516 *m_ffserver_process << "ffserver -f " << conffile; 0517 m_ffserver_out.truncate (0); 0518 connect (m_ffserver_process, 0519 SIGNAL (receivedStderr (KProcess *, char *, int)), 0520 this, SLOT (processOutput (KProcess *, char *, int))); 0521 m_ffserver_process->start (KProcess::NotifyOnExit, KProcess::Stderr); 0522 if (m_ffserver_process->isRunning ()) { 0523 m_configpage->startbutton->setText (i18n ("Stop")); 0524 m_configpage->serverled->setState (KLed::On); 0525 emit broadcastStarted (); 0526 } 0527 QTimer::singleShot (500, this, SLOT (startFeed ())); 0528 } 0529 0530 KDE_NO_EXPORT void KMPlayerBroadcastConfig::stopServer () { 0531 m_endserver = true; 0532 if (m_ffmpeg_process) 0533 m_ffmpeg_process->stop (); 0534 if (!stopProcess (m_ffserver_process)) 0535 KMessageBox::error (m_configpage, i18n ("Failed to end ffserver process."), i18n ("Error")); 0536 } 0537 0538 KDE_NO_EXPORT void KMPlayerBroadcastConfig::processOutput (KProcess * p, char * s, int) { 0539 if (p == m_ffserver_process) 0540 m_ffserver_out += QString (s); 0541 } 0542 0543 KDE_NO_EXPORT void KMPlayerBroadcastConfig::startFeed () { 0544 if (!m_configpage) { 0545 stopServer (); 0546 return; 0547 } 0548 FFServerSetting ffs; 0549 m_configpage->getSettings (ffs); 0550 QString ffurl; 0551 if (!m_ffserver_process || !m_ffserver_process->isRunning ()) { 0552 KMessageBox::error (m_configpage, i18n ("Failed to start ffserver.\n") + m_ffserver_out, i18n ("Error")); 0553 goto bail_out; 0554 } 0555 disconnect (m_ffserver_process, SIGNAL (receivedStderr (KProcess *, char *, int)), 0556 this, SLOT (processOutput (KProcess *, char *, int))); 0557 if (m_ffmpeg_process) 0558 m_ffmpeg_process->stop (); 0559 delete m_ffmpeg_process; 0560 m_ffmpeg_process = new KMPlayer::FFMpeg (m_player, NULL, m_player->settings ()); 0561 connect (m_ffmpeg_process, SIGNAL (stateChange (KMPlayer::Process::State, KMPlayer::Process::State)), this, SLOT (stateChange (KMPlayer::Process::State, KMPlayer::Process::State))); 0562 ffurl.sprintf ("http://localhost:%d/kmplayer.ffm", m_ffserverconfig->ffserverport); 0563 //m_ffmpeg_process->setUrl (KUrl(ffurl)); 0564 if (!m_ffmpeg_process->play ()) { 0565 KMessageBox::error (m_configpage, i18n ("Failed to start ffmpeg."), i18n ("Error")); 0566 stopProcess (m_ffserver_process); 0567 goto bail_out; 0568 } 0569 if (m_ffmpeg_process->running ()) { 0570 m_ffserver_url.sprintf ("http://localhost:%d/video.%s", m_ffserverconfig->ffserverport, ffs.format.ascii ()); 0571 m_endserver = false; 0572 m_configpage->feedled->setState (KLed::On); 0573 m_player->openUrl (KUrl (m_ffserver_url)); 0574 } else 0575 stopServer (); 0576 bail_out: 0577 m_configpage->setCursor (QCursor (Qt::ArrowCursor)); 0578 } 0579 /* 0580 KDE_NO_EXPORT void KMPlayerBroadcastConfig::stateChange (KMPlayer::Process::State old, KMPlayer::Process::State state) { 0581 if (state < KMPlayer::Process::Buffering && old >KMPlayer::Process::Ready) { 0582 if (m_configpage) 0583 m_configpage->feedled->setState (KLed::Off); 0584 m_ffmpeg_process->deleteLater (); 0585 m_ffmpeg_process = 0L; 0586 kdDebug () << "ffmpeg process stopped " << m_endserver << endl; 0587 if (m_endserver && !stopProcess (m_ffserver_process)) { 0588 disconnect (m_ffserver_process, 0589 SIGNAL (receivedStderr (KProcess *, char *, int)), 0590 this, SLOT (processOutput (KProcess *, char *, int))); 0591 KMessageBox::error (m_configpage, i18n ("Failed to end ffserver process."), i18n ("Error")); 0592 processStopped (0L); 0593 } 0594 } 0595 } 0596 */ 0597 KDE_NO_EXPORT void KMPlayerBroadcastConfig::processStopped (KProcess *) { 0598 kdDebug () << "ffserver process stopped" << endl; 0599 if (m_configpage) { 0600 m_configpage->serverled->setState (KLed::Off); 0601 m_configpage->startbutton->setText (i18n ("Start")); 0602 m_configpage->startbutton->setEnabled 0603 (!m_player->source ()->videoDevice ().isEmpty ()); 0604 } 0605 m_ffserver_process->deleteLater (); 0606 m_ffserver_process = 0L; 0607 emit broadcastStopped (); 0608 } 0609 0610 KDE_NO_EXPORT void KMPlayerBroadcastConfig::sourceChanged (KMPlayer::Source *, KMPlayer::Source * source) { 0611 if (m_configpage) 0612 m_configpage->startbutton->setEnabled (broadcasting () || (source && !source->videoDevice ().isEmpty ())); 0613 } 0614 //----------------------------------------------------------------------------- 0615 0616 KDE_NO_CDTOR_EXPORT KMPlayerFFServerConfig::KMPlayerFFServerConfig () { 0617 } 0618 0619 KDE_NO_EXPORT void KMPlayerFFServerConfig::write (KConfig * config) { 0620 config->setGroup (strBroadcast); 0621 config->writeEntry (strBindAddress, bindaddress); 0622 config->writeEntry (strFFServerPort, ffserverport); 0623 config->writeEntry (strMaxClients, maxclients); 0624 config->writeEntry (strMaxBandwidth, maxbandwidth); 0625 config->writePathEntry (strFeedFile, feedfile); 0626 config->writeEntry (strFeedFileSize, feedfilesize); 0627 } 0628 0629 KDE_NO_EXPORT void KMPlayerFFServerConfig::read (KConfig * config) { 0630 config->setGroup (strBroadcast); 0631 bindaddress = config->readEntry (strBindAddress, "0.0.0.0"); 0632 ffserverport = config->readNumEntry (strFFServerPort, 8090); 0633 maxclients = config->readNumEntry (strMaxClients, 10); 0634 maxbandwidth = config->readNumEntry (strMaxBandwidth, 1000); 0635 feedfile = config->readPathEntry (strFeedFile, "/tmp/kmplayer.ffm"); 0636 feedfilesize = config->readNumEntry (strFeedFileSize, 512); 0637 } 0638 0639 KDE_NO_EXPORT void KMPlayerFFServerConfig::sync (bool fromUI) { 0640 if (fromUI) { 0641 bindaddress = m_configpage->bindaddress->text (); 0642 ffserverport = m_configpage->port->text ().toInt (); 0643 maxclients = m_configpage->maxclients->text ().toInt (); 0644 maxbandwidth = m_configpage->maxbandwidth->text ().toInt(); 0645 feedfile = m_configpage->feedfile->text (); 0646 feedfilesize = m_configpage->feedfilesize->text ().toInt(); 0647 } else { 0648 m_configpage->bindaddress->setText (bindaddress); 0649 m_configpage->port->setText (QString::number (ffserverport)); 0650 m_configpage->maxclients->setText (QString::number (maxclients)); 0651 m_configpage->maxbandwidth->setText (QString::number (maxbandwidth)); 0652 m_configpage->feedfile->setText (feedfile); 0653 m_configpage->feedfilesize->setText (QString::number (feedfilesize)); 0654 } 0655 } 0656 0657 KDE_NO_EXPORT void KMPlayerFFServerConfig::prefLocation (QString & item, QString & icon, QString & tab) { 0658 item = i18n ("Broadcasting"); 0659 icon = QString ("share"); 0660 tab = i18n ("FFServer"); 0661 } 0662 0663 KDE_NO_EXPORT QFrame *KMPlayerFFServerConfig::prefPage (QWidget * parent) { 0664 if (!m_configpage) 0665 m_configpage = new KMPlayerPrefBroadcastPage (parent); 0666 return m_configpage; 0667 } 0668 0669 0670 #include "kmplayerbroadcast.moc"