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