/* * Copyright (C) 2005, 2006 Liu Di * * Copyright (C) 2007 Wei Lian * * 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sopfork.h" #include "record.h" #include "header.h" #include "config.h" #include "channel.h" #include "timing.h" #include "tabwidget.h" #include "mainwindow.h" #include "menubar.h" #include "utils.h" #include "mystatusbar.h" Record::Record (QWidget * parent, const char *name): MyVBox (parent, name), tabwidget (static_cast < TabWidget * >(parent)) { ///set page type pagetype = "record"; recordfp = new QFile (); snrecord = 0; launchtimer = new QTimer (this); connect (launchtimer, SIGNAL (timeout ()), this, SLOT (launchRecord ())); quittimer = new QTimer (this); connect (quittimer, SIGNAL (timeout ()), this, SLOT (quitRecord ())); ///row QHBox *hbox = new QHBox (this); ///status bar statusbar = new QStatusBar (hbox); statusbar->setSizeGripEnabled (false); statusbar->hide (); ///input for timing timing = new Timing (hbox); ///button record buttonrecord = new QToolButton (hbox); buttonrecord->setTextLabel (tr ("Record")); buttonrecord->setAutoRaise (true); buttonrecord->setUsesTextLabel (true); buttonrecord->setToggleButton (TRUE); // buttonrecord->setMaximumSize(buttonrecord->sizeHint()); //signal connect (buttonrecord, SIGNAL (toggled (bool)), this, SLOT (onButtonRecordToggled (bool))); ///button delete QToolButton *but = new QToolButton (hbox); but->setTextLabel (tr ("x")); but->setAutoRaise (true); but->setUsesTextLabel (true); but->setMaximumSize (but->sizeHint ()); connect (but, SIGNAL (clicked ()), this, SLOT (removeTab ())); ///initialize flagMenu flagMenu = false; } Record::~Record () { tabwidget->detachSop (&sopfork, this); /// if (snrecord) { recordfp->close (); ::close (snrecord->socket ()); delete snrecord; snrecord = 0; } delete recordfp; } void Record::streamReady (int fd) { int ret; char buff[1024]; ret =::read (fd, buff, sizeof (buff)); if (ret <= 0) { if (ret < 0) perror ("record socketnotifier"); recordfp->close (); ::close (fd); delete snrecord; snrecord = 0; buttonrecord->setPaletteForegroundColor (Qt::black); /////restart record launchtimer->start (2000, true); return; } ::write (recordfp->handle (), buff, ret); } void Record::launchRecord () { ///show message on statusbar static_cast < MainWindow * >(qApp->mainWidget ()) ->statusbar->showMessage (tr ("Connecting...")); ////launch Sop if (!sopfork) { if (tabwidget->attachSop (&sopfork, this, channelurl, channelname) == TRUE) { } else fprintf (stderr, "failed to launch sp-sc!\n"); } else if (sopfork->channelurl != channelurl) { tabwidget->detachSop (&sopfork, this); if (tabwidget->attachSop (&sopfork, this, channelurl, channelname) == TRUE) { } else fprintf (stderr, "failed to launch sp-sc!\n"); } ////handle stream int sockfd = connect_to_server ("127.0.0.1", atoi (sopfork->outport)); if (sockfd < 0) { ///restart launchtimer->start (2000, true); return; } ::write (sockfd, "1",::strlen ("1") + 1); ///parse header char buf[19]; if (::recv (sockfd, buf, sizeof (buf), 0) != sizeof (buf)) { fprintf (stderr, "err while parsing head\n"); ::close (sockfd); buttonrecord->setOn (false); return; } ///testing data availibility int nread; ::ioctl (sockfd, FIONREAD, &nread); if (nread <= 0) { ::close (sockfd); //// if (nread < 0) perror ("ioctl get nread of socket"); ///restart launchtimer->start (2000, true); return; } ////data availible QString data_path = static_cast < MainWindow * >(qApp->mainWidget ()) ->vboxconfig->editrecorddir->text (); QDir dir (data_path); if (!dir.exists ()) if (!dir.mkdir (data_path)) { perror ("failed to create record path"); ::close (sockfd); buttonrecord->setOn (false); return; } data_path += sopfork->channelname.replace (QRegExp ("\\/+"), "#"); ///eliminate harmful character data_path += QDateTime::currentDateTime ().toString (); data_path += ".asf"; recordfp->setName (data_path); if (!recordfp->open (IO_WriteOnly)) { perror ("record file name is invalid"); ::close (sockfd); buttonrecord->setOn (false); return; } if (snrecord) { fprintf (stderr, "QSocketNotifier exist!\n"); return; } snrecord = new QSocketNotifier (sockfd, QSocketNotifier::Read, this); connect (snrecord, SIGNAL (activated (int)), SLOT (streamReady (int))); buttonrecord->setPaletteForegroundColor (Qt::red); } void Record::quitRecord () { buttonrecord->setOn (false); } void Record::onButtonRecordToggled (bool t) { if (t) { if (!flagMenu) { ///if not launched from bookmark or history QListViewItem *item = static_cast < MainWindow * >(qApp->mainWidget ()) ->channel->currentItem (); if (!item || item->depth () != 1) { buttonrecord->setOn (false); return; } ///get channel name and url channelname = item->text (NAME_COLUMN); channelurl = item->text (URL_COLUMN); channeltype = item->text (STREAM_COLUMN); } ///get time for current, from and to int current = QTime::currentTime ().hour () * 60 * 60 + QTime::currentTime ().minute () * 60 + QTime::currentTime ().second (); int from = timing->fromHour->text ().toInt () * 60 * 60 + timing->fromMinute->text ().toInt () * 60; int to = timing->toHour->text ().toInt () * 60 * 60 + timing->toMinute->text ().toInt () * 60; ///calculate delay time for record start and stop int delaystart, delaystop; QString fromdaytime, todaytime; if (timing->fromHour->text ().isEmpty () && timing->toHour->text ().isEmpty ()) { delaystart = 0; delaystop = -1; /// fromdaytime = tr ("today/now"); todaytime = tr ("inf"); } else if (timing->fromHour->text ().isEmpty ()) { delaystart = 0; delaystop = to - current >= 0 ? to - current : to - current + 24 * 60 * 60; /// fromdaytime = tr ("today/now"); todaytime = to - current >= 0 ? tr ("today/") : tr ("tomor/"); todaytime += timing->toHour->text () + ":" + timing->toMinute->text (); /// } else if (timing->toHour->text ().isEmpty ()) { delaystart = from - current >= 0 ? from - current : from - current + 24 * 60 * 60; delaystop = -1; /// fromdaytime = from - current >= 0 ? tr ("today/") : tr ("tomor/"); fromdaytime += timing->fromHour->text () + ":" + timing->fromMinute->text (); todaytime = tr ("inf"); /// } else { delaystart = from - current >= 0 ? from - current : from - current + 24 * 60 * 60; delaystop = to - from >= 0 ? to - from : to - from + 24 * 60 * 60; delaystop = delaystop + delaystart; /// fromdaytime = from - current >= 0 ? tr ("today/") : tr ("tomor/"); fromdaytime += timing->fromHour->text () + ":" + timing->fromMinute->text (); switch ((from - current < 0) + (to - from < 0)) { case 0: todaytime = tr ("today/"); break; case 1: todaytime = tr ("tomor/"); break; case 2: todaytime = tr ("aftto/"); } todaytime += timing->toHour->text () + ":" + timing->toMinute->text (); } ///start timer for starting record launchtimer->start (delaystart * 1000, true); ///start timer for stoping record if (delaystop >= 0) { quittimer->start (delaystop * 1000, true); } ///change interface statusbar->message (fromdaytime + "-" + todaytime + "|" + channelname); statusbar->show (); timing->hide (); ///log printf ("record start after %d hour and %d minute %d second\n", delaystart / 3600, delaystart / 60 % 60, delaystart % 60); if (delaystop >= 0) printf (" and stop after %d hour and %d minute %d second\n", delaystop / 3600, delaystop / 60 % 60, delaystop % 60); ///assign channel name to tab label tabwidget->setTabLabel (this, reduceLabelLength (channelname)); ///add to history static_cast < MainWindow * >(qApp->mainWidget ()) ->menubar->addToPopupMenu (static_cast < MainWindow * > (qApp->mainWidget ())-> menubar->history, channelurl, channelname, channeltype); } else ///function setOn(false) will trigger the following code { ///close file, socket and socketnotifier if (snrecord) { recordfp->close (); ::close (snrecord->socket ()); delete snrecord; snrecord = 0; } ///reset button color buttonrecord->setPaletteForegroundColor (Qt::black); ///stop timer launchtimer->stop (); quittimer->stop (); ///change interface statusbar->hide (); timing->show (); ///kill sop tabwidget->detachSop (&sopfork, this); ///assign channel name to tab label tabwidget->setTabLabel (this, tr ("record")); ///clean statusbar static_cast < MainWindow * >(qApp->mainWidget ()) ->statusbar->showMessage (""); } } void Record::removeTab () { if (tabwidget->count () == 1) return; tabwidget->removePage (this); delete this; }