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

mmscda.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 
00033 #include <fstream>
00034 #include <cstdlib>
00035 #include <cerrno>
00036 #include "mmsmedia/mmscda.h"
00037 extern "C" {
00038 #include <linux/cdrom.h>
00039 #include <sys/ioctl.h>
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #include <fcntl.h>
00043 }
00044 
00045 MMS_CREATEERROR(MMSCDAError);
00046 
00047 #ifdef __HAVE_GSTREAMER__
00048 #endif
00049 #ifdef __HAVE_XINE__
00050 /**
00051  * Callback, that will be called if xine sends event messages.
00052  *
00053  * At the moment it just handles the error message if an encrypted
00054  * dvd cannot be played and it updates the channel information.
00055  *
00056  * It also emits signals that can be handled by sigc++ connectors.
00057  *
00058  * @param   userData    [in/out]    pointer to the MMSCDA object
00059  * @param   event       [in]        pointer to event structure
00060  */
00061 static void queue_cb(void *userData, const xine_event_t *event) {
00062     MMSCDA                 *mmscda = (MMSCDA*)userData;
00063     //xine_ui_message_data_t *msg    = (xine_ui_message_data_t*)event->data;
00064     switch(event->type) {
00065         case XINE_EVENT_UI_PLAYBACK_FINISHED:
00066             mmscda->onStatusChange->emit(103,0);
00067             break;
00068     }
00069 }
00070 #endif
00071 
00072 /**
00073  * Check for CD device.
00074  *
00075  * It uses xine health check to implement this.
00076  * First it will check for a given device. If it fails
00077  * it also checks for '/dev/dvd'.
00078  *
00079  * @param   device  [in]    device to check as dvd device
00080  *
00081  * @exception   MMSCDAError no usable dvd device found
00082  */
00083 void MMSCDA::checkDevice(const string device) {
00084     if (this->backend == MMSMEDIA_BE_GST) {
00085 #ifdef __HAVE_GSTREAMER__
00086 #endif
00087     }
00088     else {
00089 #ifdef __HAVE_XINE__
00090         string                  d = device;
00091         xine_health_check_t hc, *result;
00092 
00093         if(d.length() == 0)
00094             d = "/dev/cdrom";
00095 
00096         hc.cdrom_dev = xine_config_register_string(xine, "input.cdrom_dev", d.c_str(), "device used as cdrom drive", NULL, 0, NULL, NULL);
00097         result = xine_health_check(&hc, CHECK_CDROM);
00098         if(result->status != XINE_HEALTH_CHECK_OK) {
00099                 throw MMSCDAError(0, "No DVD Device found at " + d);
00100         }
00101 
00102         this->device = d;
00103         DEBUGMSG("MMSMedia", "Using " + this->device + " as CDROM device");
00104 #endif
00105     }
00106 }
00107 
00108 /**
00109  * Constructor of MMSCDA class.
00110  *
00111  * It does initializing by calling MMSAV::initialize()
00112  * and checks the given device. If the device is not correct
00113  * "/dev/dvd" will be used.
00114  *
00115  * @param   window  [in]    main window for dvd playing
00116  * @param   device  [in]    device to check as dvd device
00117  * @param   verbose [in]    if true the xine engine writes debug messages to stdout
00118  */
00119 MMSCDA::MMSCDA(MMSWindow *window, const string device, const bool verbose)  {
00120     MMSAV::initialize(verbose, window);
00121 
00122     /* at first check for DVD device */
00123     checkDevice(device);
00124 
00125     /* save window width/height */
00126     if(window) {
00127         MMSFBRectangle rect = window->getGeometry();
00128         this->windowWidth  = rect.w;
00129         this->windowHeight = rect.h;
00130     }
00131 }
00132 
00133 /**
00134  * Destructor of MMSCDA class.
00135  */
00136 MMSCDA::~MMSCDA() {
00137 }
00138 
00139 #if defined __HAVE_GSTREAMER__
00140 #elif defined __HAVE_XINE__
00141 /**
00142  * Calls MMSAV::open() with the queue_cb callback.
00143  */
00144 void MMSCDA::xineOpen() {
00145     MMSAV::xineOpen(queue_cb, (void*)this);
00146 }
00147 #endif
00148 
00149 /**
00150  * Starts playing.
00151  *
00152  * If the continue flag is set it tries to continue
00153  * at the position where it was stopped before.
00154  *
00155  * @param   cont    if true it tries to continue at a position stopped before
00156  */
00157 void MMSCDA::startPlaying(int tracknum) {
00158     string mrl = "cdda://" + this->device;
00159     if(tracknum <= titlecount && tracknum >= 1)
00160         mrl += "/" + iToStr(tracknum);
00161 
00162     this->currtitle = (tracknum >= 1 ? tracknum : 1);
00163 
00164 #ifdef __HAVE_XINE__
00165     if(!this->stream) MMSAV::xineOpen(queue_cb, (void*)this);
00166 #endif
00167 
00168     MMSAV::startPlaying(mrl, false);
00169 }
00170 
00171 /**
00172  * Playback will be switched to rewind.
00173  *
00174  * @see MMSCDA::slow()
00175  * @see MMSCDA::ffwd()
00176  */
00177 void MMSCDA::rewind() {
00178     DEBUGMSG("MMSMedia", "MMSCDA::rewind() not yet implemented");
00179 #if 0
00180     if(this->status != this->STATUS_NONE) {
00181         this->setStatus(this->STATUS_REWIND);
00182         xine_trick_mode (this->stream, XINE_TRICK_MODE_FAST_REWIND, 1);
00183     }
00184 #endif
00185 }
00186 
00187 /**
00188  * Jump to previous chapter.
00189  *
00190  * @see MMSCDA::next()
00191  */
00192 void MMSCDA::previous() {
00193     if (this->backend == MMSMEDIA_BE_GST) {
00194 #ifdef __HAVE_GSTREAMER__
00195 #endif
00196     }
00197     else {
00198 #ifdef __HAVE_XINE__
00199         if(currtitle>1)
00200             currtitle--;
00201         else
00202             currtitle=titlecount;
00203         this->stop(false);
00204         this->startPlaying(currtitle);
00205 #endif
00206     }
00207     //this->setStatus(this->STATUS_PREVIOUS);
00208 }
00209 
00210 /**
00211  * Jump to next chapter.
00212  *
00213  * @see MMSCDA::previous()
00214  */
00215 void MMSCDA::next() {
00216     if (this->backend == MMSMEDIA_BE_GST) {
00217 #ifdef __HAVE_GSTREAMER__
00218 #endif
00219     }
00220     else {
00221 #ifdef __HAVE_XINE__
00222         if(currtitle<titlecount)
00223             currtitle++;
00224         else
00225             currtitle=1;
00226         this->stop(false);
00227         this->startPlaying(currtitle);
00228 #endif
00229     }
00230     //this->setStatus(this->STATUS_NEXT);
00231 }
00232 
00233 /**
00234  * Eject the cd.
00235  *
00236  * It disposes the xine stream and tries to eject dvd with ioctl
00237  *
00238  */
00239 void MMSCDA::eject() {
00240 
00241     this->setStatus(this->STATUS_NONE);
00242 
00243     if (this->backend == MMSMEDIA_BE_GST) {
00244 #ifdef __HAVE_GSTREAMER__
00245 #endif
00246     }
00247     else {
00248 #ifdef __HAVE_XINE__
00249         if(this->stream)
00250             xine_dispose(this->stream);
00251         this->stream = 0;
00252 
00253 #endif
00254     }
00255     /* eject with ioctl */
00256     int status = -1;
00257     int fd = open(device.c_str(), O_RDONLY|O_NONBLOCK);
00258 
00259     if(fd < 0) {
00260         DEBUGMSG("MMSCDA", "Eject failed (can't open device: %s.)", strerror(errno));
00261         return;
00262     }
00263 
00264 #if defined(CDROMEJECT)
00265     status = ioctl(fd, CDROMEJECT);
00266 #elif defined(CDIOCEJECT)
00267     status = ioctl(fd, CDIOCEJECT);
00268 #endif
00269 
00270     close(fd);
00271     if(status != 0) {
00272         DEBUGMSG("MMSCDA", "Eject failed: %s.", strerror(errno));
00273     }
00274 }
00275 
00276 
00277 /**
00278  * Gets the title number that is currently being played.
00279  *
00280  * @return  title number
00281  */
00282 int MMSCDA::getTitleNumber() {
00283     if (this->backend == MMSMEDIA_BE_GST) {
00284 #ifdef __HAVE_GSTREAMER__
00285         // TODO: implement getTitleNumber() for gstreamer
00286         return 0;
00287 #endif
00288     }
00289     else {
00290 #ifdef __HAVE_XINE__
00291         return this->currtitle;
00292 #endif
00293     }
00294 
00295     throw MMSCDAError(0, "MMSCDA::getTitleNumber() called but media backend does not match supported backends");
00296 }
00297 
00298 /**
00299  * Gets amount of titles available on the current dvd.
00300  *
00301  * @return  title count
00302  */
00303 int MMSCDA::getTitleCount() {
00304     if (this->backend == MMSMEDIA_BE_GST) {
00305 #ifdef __HAVE_GSTREAMER__
00306         // TODO: implement getTitleCount() for gstreamer
00307         return 0;
00308 #endif
00309     }
00310     else {
00311 #ifdef __HAVE_XINE__
00312         return this->titlecount;
00313 #endif
00314     }
00315 
00316     throw MMSCDAError(0, "MMSCDA::getTitleCount() called but media backend does not match supported backends");
00317 }
00318 
00319 
00320 void MMSCDA::checktoc() {
00321     int fd_cd = open(device.c_str(), O_RDONLY | O_NONBLOCK);
00322     if(fd_cd<0) {
00323         this->titlecount=-1;
00324         return;
00325     }
00326     struct cdrom_tochdr hdr;
00327     if(ioctl(fd_cd, CDROMREADTOCHDR, &hdr) == -1) {
00328         this->titlecount=-1;
00329     } else {
00330         DEBUGMSG("MMSMedia", "tochdr cdth_trk0: " + iToStr(hdr.cdth_trk0) + " cdth_trk1: " + iToStr(hdr.cdth_trk1));
00331         this->titlecount = hdr.cdth_trk1;
00332     }
00333 
00334     close(fd_cd);
00335 }

Generated by doxygen