Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmstv.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 #include "disko.h"
00033 #include "mmsmedia/mmstv.h"
00034 #include <strings.h>
00035 
00036 #ifdef __HAVE_XINE__
00037 #include <xine/xineutils.h>
00038 
00039 #define MMSTV_RECORD_START  XINE_EVENT_INPUT_MENU2
00040 #define MMSTV_RECORD_STOP   XINE_EVENT_INPUT_MENU2
00041 #define MMSTV_RECORD_PAUSE  XINE_EVENT_INPUT_MENU4
00042 #endif
00043 
00044 MMS_CREATEERROR(MMSTVError);
00045 
00046 #ifdef __HAVE_XINE__
00047 /**
00048  * Callback, that will be called if xine sends event messages.
00049  *
00050  * It also emits signals that can be handled by sigc++ connectors.
00051  *
00052  * @param   userData    [in/out]    pointer to the MMSTV object
00053  * @param   event       [in]        pointer to event structure
00054  */
00055 static void queue_cb(void *userData, const xine_event_t *event) {
00056     MMSTV *mmstv  = static_cast<MMSTV*>(userData);
00057 
00058     if(event->type == XINE_EVENT_UI_MESSAGE) {
00059         xine_ui_message_data_t *msg = (xine_ui_message_data_t*)event->data;
00060         DEBUGMSG("MMSTV", "event: %s", (char*)msg + msg->parameters);
00061     }
00062     else if(event->type == XINE_EVENT_PROGRESS) {
00063         xine_progress_data_t *prog = (xine_progress_data_t*)event->data;
00064         DEBUGMSG("MMSTV", "event: %s (%d%%)", prog->description, prog->percent);
00065         if(mmstv) mmstv->onProgressChange.emit(prog->percent);
00066     }
00067     else if(event->type == XINE_EVENT_UI_PLAYBACK_FINISHED) {
00068         DEBUGMSG("MMSTV", "event: signal lost");
00069         mmstv->startPlaying(mmstv->getCurrentChannelName());
00070     } else
00071         DEBUGMSG("MMSTV", "event: %u", event->type);
00072 }
00073 #endif
00074 
00075 /**
00076  * Initializes everything that is needed by MMSTV.
00077  *
00078  * The timeout attribute is set to 10 seconds.
00079  *
00080  * @param   window      [in]    main window for dvd playing
00081  * @param   _channel    [in]    channel to open
00082  * @param   verbose     [in]    if true the xine engine writes debug messages to stdout
00083  *
00084  * @see MMSAV::MMSAV()
00085  * @see MMSAV::initialize()
00086  */
00087 #ifdef __HAVE_XINE_BLDVB__
00088 MMSTV::MMSTV(MMSWindow *window, const string _channel, const bool verbose, const bool _useBlDvb) :
00089 #else
00090 MMSTV::MMSTV(MMSWindow *window, const string _channel, const bool verbose) :
00091 #endif
00092             channel(_channel),
00093             captureFilename(""),
00094             recording(false)
00095 #ifdef __HAVE_XINE_BLDVB__
00096             , useBlDvb(_useBlDvb)
00097 #endif
00098 {
00099     MMSAV::initialize(verbose, window);
00100     setTuningTimeout(10);
00101 }
00102 
00103 /**
00104  * Destructor of MMSTV class.
00105  */
00106 MMSTV::~MMSTV() {
00107 }
00108 
00109 #ifdef __HAVE_XINE__
00110 /**
00111  * Calls MMSAV::open() with the queue_cb callback.
00112  */
00113 void MMSTV::xineOpen() {
00114     MMSAV::xineOpen(queue_cb, this);
00115 }
00116 #endif
00117 
00118 /**
00119  * Starts playing.
00120  *
00121  * If usingInputDVBMorphine is set, it tries to use our own
00122  * input plugin for playback.
00123  *
00124  * @param   channel [in]    channel name to be played
00125  */
00126 void MMSTV::startPlaying(const string channel) {
00127 #ifdef __HAVE_XINE__
00128   this->xineOpen();
00129 #endif
00130 
00131     if(strncasecmp(channel.c_str(), "OTH:",4)==0) {
00132         FILE *fp;
00133         fp=fopen(channel.c_str(),"r");
00134         if(fp!=NULL){
00135             char line[1024];
00136             if(!fgets(line,1024,fp))
00137                 throw MMSTVError(0, "Error reading from file " + channel);
00138             this->channel = line;
00139             fclose(fp);
00140             DEBUGMSG("MMSTV", "trying to play " + this->channel);
00141             MMSAV::startPlaying(this->channel, false);
00142         }
00143 
00144     } else {
00145         DEBUGMSG("MMSTV", "trying to play " + this->channel);
00146 #ifdef __HAVE_XINE_BLDVB__
00147         if(this->useBlDvb)
00148             MMSAV::startPlaying("bldvb://" + channel, false);
00149         else
00150 #endif
00151         MMSAV::startPlaying("dvb://" + channel, false);
00152         this->channel = channel;
00153     }
00154 }
00155 
00156 /**
00157  * Continues playing the stream.
00158  *
00159  * If recording is on, it will be continued, too.
00160  */
00161 void MMSTV::play() {
00162     //TODO: recording
00163     //this->recordPause();
00164     MMSAV::play();
00165 }
00166 
00167 #ifdef __HAVE_XINE_BLDVB__
00168 void MMSTV::play(const string &channel) {
00169     if(this->useBlDvb) {
00170         if(this->isPlaying()) {
00171             char *ch = strdup(channel.c_str());
00172             this->sendEvent(XINE_EVENT_INPUT_SELECT, ch, sizeof(char) * (strlen(ch) + 1));
00173             free(ch);
00174         } else
00175             this->startPlaying(channel);
00176     } else
00177         this->next();
00178 }
00179 #endif
00180 
00181 /**
00182  * Pauses the stream.
00183  *
00184  * If recording is on, it will be paused, too.
00185  */
00186 void MMSTV::pause() {
00187     this->recordPause();
00188     MMSAV::pause();
00189 }
00190 
00191 /**
00192  * Switch to previous channel.
00193  *
00194  * @see MMSTV::next()
00195  */
00196 void MMSTV::previous() {
00197     switch(this->backend) {
00198         case MMSMEDIA_BE_GST:
00199             break;
00200         case MMSMEDIA_BE_XINE:
00201 #ifdef __HAVE_XINE__
00202             this->sendEvent(XINE_EVENT_INPUT_PREVIOUS);
00203 #endif
00204             break;
00205         default:
00206             // shouldn't be reached
00207             break;
00208     }
00209 }
00210 
00211 /**
00212  * Switch to next channel.
00213  *
00214  * @see MMSTV::previous()
00215  */
00216 void MMSTV::next() {
00217     switch(this->backend) {
00218         case MMSMEDIA_BE_GST:
00219             break;
00220         case MMSMEDIA_BE_XINE:
00221 #ifdef __HAVE_XINE__
00222             this->sendEvent(XINE_EVENT_INPUT_NEXT);
00223 #endif
00224             break;
00225         default:
00226             // shouldn't be reached
00227             break;
00228     }
00229 }
00230 
00231 /**
00232  * Start/Stop recording.
00233  */
00234 void MMSTV::record() {
00235     switch(this->backend) {
00236         case MMSMEDIA_BE_GST:
00237             break;
00238         case MMSMEDIA_BE_XINE:
00239 #ifdef __HAVE_XINE__
00240             if(this->recording)
00241                 this->sendEvent(MMSTV_RECORD_STOP);
00242             else
00243                 this->sendEvent(MMSTV_RECORD_START);
00244             this->recording = !this->recording;
00245 #endif
00246             break;
00247         default:
00248             // shouldn't be reached
00249             break;
00250     }
00251 }
00252 
00253 /**
00254  * Start recording.
00255  */
00256 void MMSTV::recordStart() {
00257     switch(this->backend) {
00258         case MMSMEDIA_BE_GST:
00259             break;
00260         case MMSMEDIA_BE_XINE:
00261 #ifdef __HAVE_XINE__
00262             if(!this->recording) {
00263                 this->sendEvent(MMSTV_RECORD_START);
00264                 this->recording = true;
00265             }
00266 #endif
00267             break;
00268         default:
00269             // shouldn't be reached
00270             break;
00271     }
00272 }
00273 
00274 /**
00275  * Stop recording.
00276  */
00277 void MMSTV::recordStop() {
00278     switch(this->backend) {
00279         case MMSMEDIA_BE_GST:
00280             break;
00281         case MMSMEDIA_BE_XINE:
00282 #ifdef __HAVE_XINE__
00283             if(this->recording) {
00284                 this->sendEvent(MMSTV_RECORD_STOP);
00285                 this->recording = false;
00286             }
00287 #endif
00288             break;
00289         default:
00290             // shouldn't be reached
00291             break;
00292     }
00293 }
00294 
00295 /**
00296  * Pause recording.
00297  */
00298 void MMSTV::recordPause() {
00299     switch(this->backend) {
00300         case MMSMEDIA_BE_GST:
00301             break;
00302         case MMSMEDIA_BE_XINE:
00303 #ifdef __HAVE_XINE__
00304             if(this->recording)
00305                 this->sendEvent(MMSTV_RECORD_PAUSE);
00306 #endif
00307             break;
00308         default:
00309             // shouldn't be reached
00310             break;
00311     }
00312 }
00313 
00314 /**
00315  * Retrieve the current channel name.
00316  *
00317  * @return  current channel name
00318  */
00319 string MMSTV::getCurrentChannelName(void) {
00320     return this->channel;
00321 }
00322 
00323 /**
00324  * Sets the maximum time for tuning to a channel.
00325  *
00326  * @param   timeout [in]    timeout in seconds
00327  *
00328  * @note A value of 0 means infinite. Otherwise a minimum of 5
00329  * seconds is required.
00330  *
00331  * @see MMSTV::getTuningTimeout()
00332  */
00333 void MMSTV::setTuningTimeout(const unsigned int timeout) {
00334     if (this->backend == MMSMEDIA_BE_GST) {
00335 #ifdef __HAVE_GSTREAMER__
00336 #endif
00337     }
00338     else {
00339 #ifdef __HAVE_XINE__
00340         xine_cfg_entry_t  conf;
00341 
00342         if(!this->xine) return;
00343         this->timeout = timeout;
00344 
00345         if(xine_config_lookup_entry(this->xine, "media.dvb.tuning_timeout", &conf)) {
00346             conf.num_value = timeout;
00347             xine_config_update_entry(this->xine, &conf);
00348         }
00349         else
00350             xine_config_register_num(this->xine, "media.dvb.tuning_timeout", timeout,
00351                                      "Number of seconds until tuning times out.",
00352                                      "Leave at 0 means try forever. "
00353                                      "Greater than 0 means wait that many seconds to get a lock. Minimum is 5 seconds.",
00354                                      XINE_CONFIG_SECURITY, NULL, NULL);
00355 #endif
00356     }
00357 }
00358 
00359 /**
00360  * Returns the setting for the tuning timeout.
00361  *
00362  * @return timeout in seconds
00363  *
00364  * @see MMSTV::setTuningTimeout()
00365  */
00366 const unsigned int MMSTV::getTuningTimeout() {
00367     return this->timeout;
00368 }
00369 
00370 /**
00371  * Sets the directory where tv recordings will be stored.
00372  *
00373  * It actually changes the value of the xine config option
00374  * "media.capture.save_dir".
00375  *
00376  * @param   dir [in]    directory to save recordings into
00377  */
00378 void MMSTV::setRecordDir(const string dir) {
00379     if (this->backend == MMSMEDIA_BE_GST) {
00380 #ifdef __HAVE_GSTREAMER__
00381 #endif
00382     }
00383     else {
00384 #ifdef __HAVE_XINE__
00385     xine_cfg_entry_t  conf;
00386 
00387     if(!this->xine) return;
00388 
00389     if(xine_config_lookup_entry(this->xine, "media.capture.save_dir", &conf)) {
00390         conf.str_value = strdup(dir.c_str());
00391         xine_config_update_entry(this->xine, &conf);
00392     }
00393     else
00394 #ifdef XINE_CONFIG_STRING_IS_DIRECTORY_NAME
00395         xine_config_register_filename(this->xine,
00396                 "media.capture.save_dir",
00397                 dir.c_str(),
00398                 XINE_CONFIG_STRING_IS_DIRECTORY_NAME,
00399 #else
00400         xine_config_register_string(this->xine,
00401                 "media.capture.save_dir",
00402                 dir.c_str(),
00403 #endif
00404                 "directory for saving streams",
00405                 NULL,
00406                 XINE_CONFIG_SECURITY,
00407                 NULL ,
00408                 NULL);
00409 #endif
00410     }
00411 }
00412 
00413 /**
00414  * Retrieves the directory where tv recordings will be stored.
00415  *
00416  * @return  current recordings dir
00417  */
00418 const string MMSTV::getRecordDir() {
00419     if (this->backend == MMSMEDIA_BE_GST) {
00420 #ifdef __HAVE_GSTREAMER__
00421 #endif
00422     }
00423     else {
00424 #ifdef __HAVE_XINE__
00425         xine_cfg_entry_t  conf;
00426 
00427         if(this->xine && xine_config_lookup_entry(this->xine, "media.capture.save_dir", &conf))
00428             return string(conf.str_value);
00429 
00430         return xine_get_homedir();
00431 #endif
00432     }
00433 
00434     return "";
00435 }
00436 
00437 /**
00438  * Retrieves the filename of the current recording if
00439  * recording is on.
00440  *
00441  * @return  current recording filename or "" if nothing is recorded
00442  */
00443 const string MMSTV::getRecordFilename() {
00444     if(this->recording)
00445         return this->captureFilename;
00446 
00447     return "";
00448 }

Generated by doxygen