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

mmsav.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 "mmsmedia/mmsav.h"
00034 #ifdef __HAVE_DIRECTFB__
00035 #include <directfb_version.h>
00036 #endif
00037 #include <string.h>
00038 #include <stdlib.h>
00039 
00040 #include "mmsmedia/mmsgst.h"
00041 
00042 
00043 MMS_CREATEERROR(MMSAVError);
00044 
00045 
00046 #ifdef __HAVE_GSTREAMER__
00047 
00048 static void* gstPlayRoutine(GST_DISKOVIDEOSINK_DATA *gst_diskovideosink_data) {
00049 
00050     printf("uri %s\n", gst_diskovideosink_data->uri.c_str());
00051 
00052     if (gst_diskovideosink_data->pipeline) {
00053         // playing gstreamer pipe
00054         mmsGstPlay(gst_diskovideosink_data->pipeline);
00055     }
00056 
00057     return NULL;
00058 }
00059 
00060 #endif
00061 
00062 
00063 
00064 
00065 #ifdef __HAVE_XINE__
00066 
00067 #ifdef __HAVE_DIRECTFB__
00068 DFBResult dfbres;
00069 #define THROW_DFB_ERROR(dfbres,msg) {if (dfbres) { string s1 = msg; string s2 = DirectFBErrorString((DFBResult)dfbres); throw MMSAVError(dfbres,s1 + " [" + s2 + "]"); }else{ throw MMSAVError(0,msg); }}
00070 #endif
00071 
00072 /**
00073  * Callback, that will be called before a frame is drawn.
00074  *
00075  * It checks if the ratio has changed and sets some variables if so.
00076  *
00077  * @param   cdata       [in/out]    pointer to VODESC structure
00078  * @param   width       [in]        width of dvd stream
00079  * @param   height      [in]        height of dvd stream
00080  * @param   ratio       [in]        ratio of dvd stream
00081  * @param   format      [in]        pixel format of dvd stream
00082  * @param   dest_rect   [out]       the current rectangle will be returned
00083  */
00084 #ifdef __HAVE_DIRECTFB__
00085 static void dfb_output_cb(void *cdata, int width, int height, double ratio,
00086                           DFBSurfacePixelFormat format, DFBRectangle* dest_rect) {
00087     VODESC *vodesc = (VODESC *) cdata;
00088     int    newH, newW;
00089 
00090     //DEBUGOUT("\noutput_cb %d:%d:%f:%d:%d",width,height,ratio,vodesc->windsc.width,vodesc->windsc.height);
00091     if (vodesc->ratio != ratio) {
00092         newW = (int)((double)(vodesc->windsc.height) * ratio + 0.5);
00093         newH = (int)((double)(vodesc->windsc.width) / ratio + 0.5);
00094 
00095         /* ratio has changed */
00096         if (ratio<1.0) {
00097             if(newW > vodesc->windsc.width) {
00098                 vodesc->rect.w = vodesc->windsc.width;
00099                 vodesc->rect.h = newH;
00100             } else {
00101                 vodesc->rect.w = newW;
00102                 vodesc->rect.h = vodesc->windsc.height;
00103             }
00104             vodesc->rect.x = (vodesc->windsc.width - vodesc->rect.w) / 2;
00105             vodesc->rect.y = 0;
00106         } else {
00107             if(newH > vodesc->windsc.height) {
00108                 vodesc->rect.h = vodesc->windsc.height;
00109                 vodesc->rect.w = newW;
00110             } else {
00111                 vodesc->rect.w = vodesc->windsc.width;
00112                 vodesc->rect.h = newH;
00113             }
00114             vodesc->rect.x = 0;
00115             vodesc->rect.y = (vodesc->windsc.height - vodesc->rect.h) / 2;
00116         }
00117 
00118         /* save other infos */
00119         vodesc->format = format;
00120         vodesc->ratio  = ratio;
00121         vodesc->width  = width;
00122         vodesc->height = height;
00123         /* clear surface */
00124         vodesc->winsurface->clear();
00125         vodesc->winsurface->flip();
00126         vodesc->winsurface->clear();
00127     }
00128 
00129     /* return the current rect */
00130     *dest_rect=(DFBRectangle&)vodesc->rect;
00131     //DEBUGOUT("\nrect %d:%d:%d:%d",dest_rect->x,dest_rect->y,dest_rect->w,dest_rect->h);
00132 
00133 }
00134 #endif
00135 
00136 
00137 /*static void printFrameFormat(int frame_format) {
00138     switch(frame_format) {
00139         case XINE_VORAW_YV12:
00140             printf("YV12 frame\n");
00141             break;
00142         case XINE_VORAW_YUY2:
00143             printf("YUY2 frame\n");
00144             break;
00145         case XINE_VORAW_RGB:
00146             printf("RGB frame\n");
00147             break;
00148         default:
00149             printf("unknown frame format\n");
00150     }
00151 }*/
00152 
00153 
00154 void raw_frame_cb(void *user_data, int frame_format, int frame_width, int frame_height, double frame_aspect, void *data0, void *data1, void *data2) {
00155     MMSRAW_USERDATA *userd =(MMSRAW_USERDATA *)user_data;
00156 /*  printf("-------\nframe format: ");
00157     printFrameFormat(frame_format);
00158     printf("frame_width: %d\n", frame_width);
00159     printf("frame_height: %d\n", frame_height);
00160     printf("frame_height: %f\n", frame_aspect);
00161     printf("plane0: %p\n", data0);
00162     printf("plane1: %p\n", data1);
00163     printf("plane2: %p\n", data2);
00164     printf("-------\n");*/
00165 
00166     if(!userd) {
00167         //there is no window to draw on!
00168         return;
00169     }
00170 
00171     if (userd->lastaspect != frame_aspect) {
00172         // format changed
00173         printf("format change %f\n", frame_aspect);
00174         int newW = (int)((double)(userd->size.h) * frame_aspect + 0.5);
00175         int newH = (int)((double)(userd->size.w) / frame_aspect + 0.5);
00176 
00177         /* ratio has changed */
00178         if (frame_aspect<1.0) {
00179             if(newW > userd->size.w) {
00180                 userd->dest.w = userd->size.w;
00181                 userd->dest.h = newH;
00182             } else {
00183                 userd->dest.w = newW;
00184                 userd->dest.h = userd->size.w;
00185             }
00186 
00187             userd->dest.x = (userd->size.w - userd->dest.w) / 2;
00188             userd->dest.y = 0;
00189         } else {
00190             if(newH > userd->size.h) {
00191                 userd->dest.h = userd->size.h;
00192                 userd->dest.w = newW;
00193             } else {
00194                 userd->dest.w = userd->size.w;
00195                 userd->dest.h = newH;
00196             }
00197             userd->dest.x = (userd->size.w - userd->dest.w) / 2;;
00198             userd->dest.y = (userd->size.h - userd->dest.h) / 2;
00199         }
00200 
00201         userd->lastaspect  = frame_aspect;
00202         /* clear surface */
00203         userd->surf->clear();
00204         userd->surf->flip(NULL);
00205         userd->surf->clear();
00206 
00207         // printf("w,h,x,y: %d, %d, %d, %d\n", userd->dest.w,userd->dest.h,userd->dest.x,userd->dest.y);
00208         userd->dest.w&=~0x01;
00209         userd->dest.h&=~0x01;
00210         userd->dest.x&=~0x01;
00211         userd->dest.y&=~0x01;
00212         // printf("w,h,x,y: %d, %d, %d, %d\n", userd->dest.w,userd->dest.h,userd->dest.x,userd->dest.y);
00213 
00214         // delete iterim surface
00215         if (userd->interim) {
00216             delete userd->interim;
00217             userd->interim = NULL;
00218         }
00219     }
00220 
00221 
00222 /*
00223 ////// TEST //////////////////////////////////////
00224 static unsigned char rrrrr_buf[2048*768];
00225 static int rrrrr=0;
00226 if(!rrrrr) {
00227     rrrrr=1;
00228     for (int i = 0; i < sizeof(rrrrr_buf)/4; i++) {
00229         rrrrr_buf[i*4] = 0xff;
00230         rrrrr_buf[i*4+1] = 0x00;
00231         rrrrr_buf[i*4+2] = 0x00;
00232         rrrrr_buf[i*4+3] = 0x00;
00233     }
00234 }
00235 data0 = rrrrr_buf;
00236 frame_format = XINE_VORAW_YUY2;
00237 //////////////////////////////////////////////////
00238 */
00239 
00240     if (userd->surf_pixelformat == MMSFB_PF_YV12) {
00241         // the destination has YV12 pixelformat
00242         if ((frame_format != XINE_VORAW_YV12) && (!userd->interim)) {
00243             // have to allocate iterim buffer
00244             switch (frame_format) {
00245             case XINE_VORAW_YUY2:
00246             case XINE_VORAW_RGB:
00247                 // we get YUY2 or RGB24 data, allocate interim buffer for YV12 convertion
00248                 userd->interim = new MMSFBSurface(frame_width, frame_height, MMSFB_PF_YV12);
00249                 break;
00250             }
00251         }
00252 
00253         if (userd->interim) {
00254             // blit to interim and then stretch it
00255             switch (frame_format) {
00256             case XINE_VORAW_YUY2:
00257                 // source is YUY2
00258                 userd->interim->blitBuffer(data0, frame_width*2, MMSFB_PF_YUY2,
00259                                            frame_width, frame_height, NULL, 0, 0);
00260                 break;
00261             case XINE_VORAW_RGB:
00262                 // source is RGB24
00263                 userd->interim->blitBuffer(data0, frame_width*3, MMSFB_PF_RGB24,
00264                                            frame_width, frame_height, NULL, 0, 0);
00265                 break;
00266             }
00267             userd->surf->stretchBlit(userd->interim, NULL, &userd->dest);
00268         } else {
00269             // source is YV12
00270             MMSFBExternalSurfaceBuffer buf;
00271             buf.ptr = data0;
00272             buf.pitch = frame_width;
00273             buf.ptr2 = data1;
00274             buf.pitch2 = frame_width / 2;
00275             buf.ptr3 = data2;
00276             buf.pitch3 = frame_width / 2;
00277 
00278             userd->surf->stretchBlitBuffer(&buf, MMSFB_PF_YV12,
00279                                            frame_width, frame_height, NULL, &userd->dest);
00280         }
00281     }
00282     else {
00283         // destination with any other pixelformat
00284         if (frame_format == XINE_VORAW_YV12) {
00285             // we get YV12 data
00286             if (!userd->interim) {
00287                 // allocate interim buffer for YV12 stretch blit
00288                 userd->interim = new MMSFBSurface(userd->dest.w, userd->dest.h, MMSFB_PF_YV12);
00289                 if (userd->interim) userd->interim->setBlittingFlags(MMSFB_BLIT_ANTIALIASING);
00290             }
00291         }
00292 
00293         if (userd->interim) {
00294             // source is YV12
00295             MMSFBExternalSurfaceBuffer buf;
00296             buf.ptr = data0;
00297             buf.pitch = frame_width;
00298             buf.ptr2 = data1;
00299             buf.pitch2 = frame_width / 2;
00300             buf.ptr3 = data2;
00301             buf.pitch3 = frame_width / 2;
00302             MMSFBRectangle mydest = userd->dest;
00303             mydest.x = 0;
00304             mydest.y = 0;
00305 
00306             userd->interim->stretchBlitBuffer(&buf, MMSFB_PF_YV12,
00307                                        frame_width, frame_height, NULL, &mydest);
00308             userd->surf->blit(userd->interim, NULL, userd->dest.x, userd->dest.y);
00309 
00310         } else {
00311             // source is RGB24
00312             userd->surf->stretchBlitBuffer(data0, frame_width*3, MMSFB_PF_RGB24,
00313                                            frame_width, frame_height, NULL, &userd->dest);
00314         }
00315     }
00316 
00317 
00318     if(userd->numOverlays > 0) {
00319         int rw = (userd->dest.w << 10) / frame_width;
00320         int rh = (userd->dest.h << 10) / frame_height;
00321 
00322         // save and set blitting flags
00323         MMSFBBlittingFlags saved_flags;
00324         userd->surf->getBlittingFlags(&saved_flags);
00325         userd->surf->setBlittingFlags(MMSFB_BLIT_BLEND_ALPHACHANNEL | MMSFB_BLIT_ANTIALIASING);
00326 
00327         if (!userd->overlayInterim) {
00328             // create interim surface for stretching overlays
00329             userd->overlayInterim = new MMSFBSurface(userd->size.w, userd->size.h, MMSFB_PF_ARGB);
00330         }
00331 
00332         // for all overlays
00333         for (int i = 0; i < userd->numOverlays; ++i) {
00334             // get overlay infos
00335             raw_overlay_t *ovl = &(userd->overlays[i]);
00336 
00337             // calc x/y offsets
00338             int x = (ovl->ovl_x * rw) >> 10;
00339             if(userd->size.w > userd->dest.w) {
00340                 x += (userd->size.w - userd->dest.w) >> 1;
00341             }
00342             int y = (ovl->ovl_y * rh) >> 10;
00343             if(userd->size.h > userd->dest.h) {
00344                 y += (userd->size.h - userd->dest.h) >> 1;
00345             }
00346 
00347             // stretch to interim
00348             MMSFBRectangle dest_rect;
00349             dest_rect.x = 0;
00350             dest_rect.y = 0;
00351             dest_rect.w = (ovl->ovl_w * rw) >> 10;
00352             dest_rect.h = (ovl->ovl_h * rh) >> 10;
00353             userd->overlayInterim->stretchBlitBuffer(ovl->ovl_rgba, ovl->ovl_w * 4, MMSFB_PF_ARGB, ovl->ovl_w, ovl->ovl_h, NULL, &dest_rect);
00354 
00355             // blit to target surface
00356             userd->surf->blit(userd->overlayInterim, &dest_rect, x, y);
00357         }
00358 
00359         // restore blitting flags
00360         userd->surf->setBlittingFlags(saved_flags);
00361     }
00362 
00363     userd->surf->flip(NULL);
00364 }
00365 
00366 /**
00367  * Callback, that will be called each time an overlay state changes @see: xine.h
00368  */
00369 void raw_overlay_cb(void *user_data, int num_ovl, raw_overlay_t *overlays_array) {
00370     MMSRAW_USERDATA *userd =(MMSRAW_USERDATA *)user_data;
00371 
00372     userd->numOverlays = num_ovl;
00373     userd->overlays = overlays_array;
00374 }
00375 
00376 
00377 /**
00378  * Callback, that will be called after a frame is drawn.
00379  *
00380  * It sets clipping areas and does the flipping.
00381  *
00382  * @param   cdata       [in/out]    pointer to VODESC structure
00383  */
00384 #ifdef __HAVE_DIRECTFB__
00385 #if DIRECTFB_MAJOR_VERSION == 1
00386 static void dfb_frame_cb(void *cdata) {
00387 #else
00388 static int dfb_frame_cb(void *cdata) {
00389 #endif
00390     VODESC *vodesc = (VODESC *) cdata;
00391 /* this was for GUI optimization which is currently not active
00392 
00393     if (vodesc->rect.y > 0) {
00394         DFBRegion reg;
00395         reg.x1=0;
00396         reg.y1=0;
00397         reg.x2=vodesc->rect.w-1;
00398         reg.y2=vodesc->rect.y-1;
00399         vodesc->winsurface->setClip(&reg);
00400         vodesc->winsurface->clear();
00401         vodesc->winsurface->setClip(NULL);
00402     }
00403 
00404     if (vodesc->rect.h < vodesc->windsc.height) {
00405         DFBRegion reg;
00406         reg.x1=0;
00407         reg.y1=vodesc->rect.y+vodesc->rect.h;
00408         reg.x2=vodesc->rect.w-1;
00409         reg.y2=vodesc->windsc.height-1;
00410         vodesc->winsurface->setClip(&reg);
00411         vodesc->winsurface->clear();
00412         vodesc->winsurface->setClip(NULL);
00413     }
00414 
00415     vodesc->winsurface->flip(NULL, (MMSFBSurfaceFlipFlags)(DSFLIP_ONSYNC));
00416 */
00417 
00418     /*DFBRegion reg;
00419     reg.x1=vodesc->rect.x;
00420     reg.y1=vodesc->rect.y;
00421     reg.x2=reg.x1 + vodesc->rect.w-1;
00422     reg.y2=reg.y1 + vodesc->rect.h-1;*/
00423 
00424 
00425 //    vodesc->winsurface->flip(NULL, (MMSFBSurfaceFlipFlags)(DSFLIP_WAITFORSYNC));
00426     vodesc->winsurface->flip();
00427 
00428 
00429     //vodesc->winsurface->lock();
00430 
00431     /*          frame->surface->Unlock( frame->surface );
00432 
00433           frame->surface->Lock( frame->surface, DSLF_WRITE,
00434                                (void*)&frame->vo_frame.base[0],
00435                                (int *)&frame->vo_frame.pitches[0] );
00436 */
00437 
00438     //vodesc->winsurface->flip(NULL, (MMSFBSurfaceFlipFlags)(DSFLIP_ONSYNC));
00439     //vodesc->winsurface->flip(NULL, (MMSFBSurfaceFlipFlags)DSFLIP_NONE);
00440 
00441     //vodesc->winsurface->unlock();
00442 
00443 #if DIRECTFB_MAJOR_VERSION < 1
00444     return 0;
00445 #endif
00446 }
00447 #endif
00448 
00449 typedef struct {
00450     xine_stream_t   *stream;
00451     int             pos;
00452     short           *status;
00453     const char      *mrl;
00454     pthread_mutex_t *lock;
00455 } internalStreamData;
00456 
00457 static void* xinePlayRoutine(void *data) {
00458     if(!data) return NULL;
00459 
00460     internalStreamData *streamData = (internalStreamData*)data;
00461 
00462     pthread_mutex_lock(streamData->lock);
00463     if(*(streamData->status) == MMSAV::STATUS_PLAYING)
00464         xine_stop(streamData->stream);
00465 
00466     if(*(streamData->status) > MMSAV::STATUS_NONE)
00467         xine_close(streamData->stream);
00468 
00469     if(!xine_open(streamData->stream, streamData->mrl) || !xine_play(streamData->stream, streamData->pos, 0)) {
00470         switch(xine_get_error(streamData->stream)) {
00471             case XINE_ERROR_NO_INPUT_PLUGIN :
00472                 DEBUGMSG("MMSAV", "Error while trying to play stream: No input plugin");
00473                 break;
00474             case XINE_ERROR_NO_DEMUX_PLUGIN :
00475                 DEBUGMSG("MMSAV", "Error while trying to play stream: No demux plugin");
00476                 break;
00477             case XINE_ERROR_DEMUX_FAILED :
00478                 DEBUGMSG("MMSAV", "Error while trying to play stream: Error in demux plugin");
00479                 break;
00480             case XINE_ERROR_INPUT_FAILED :
00481                 DEBUGMSG("MMSAV", "Error while trying to play stream: Error in input plugin");
00482                 break;
00483             case XINE_ERROR_MALFORMED_MRL :
00484                 DEBUGMSG("MMSAV", "Error while trying to play stream: Malformed MRL");
00485                 break;
00486             default:
00487                 DEBUGMSG("MMSAV", "Unknown error while trying to play stream");
00488                 break;
00489         }
00490         *(streamData->status) = MMSAV::STATUS_NONE;
00491     }
00492     else
00493         *(streamData->status) = MMSAV::STATUS_PLAYING;
00494 
00495     pthread_mutex_unlock(streamData->lock);
00496     delete streamData;
00497 
00498     return NULL;
00499 }
00500 
00501 static void* stopRoutine(void *data) {
00502     if(!data) return NULL;
00503 
00504     internalStreamData *streamData = (internalStreamData*)data;
00505     pthread_mutex_lock(streamData->lock);
00506     xine_stop(streamData->stream);
00507     xine_set_param(streamData->stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
00508     xine_close(streamData->stream);
00509     *(streamData->status) = MMSAV::STATUS_STOPPED;
00510     pthread_mutex_unlock(streamData->lock);
00511     delete streamData;
00512 
00513     return NULL;
00514 }
00515 
00516 /**
00517  * Initializes some xine stuff.
00518  *
00519  * It creates the xine object that is used for
00520  * audio/video stream creation.
00521  * Then it loads the user's xine configuration and sets
00522  * the given verbosity.
00523  *
00524  * @exception   MMSAVError  cannot get a new xine object
00525  */
00526 void MMSAV::xineInit() {
00527     /* get a new xine object */
00528     if (!(this->xine = xine_new()))
00529         throw MMSAVError(0, "Cannot get a new xine object");
00530 
00531     /* load xine config */
00532     string cfg;
00533     if(getenv("XINERC"))
00534         cfg = getenv("XINERC");
00535     else {
00536         if (getenv("HOME"))
00537             cfg = string(getenv("HOME")) + "/.xine";
00538         else
00539             cfg = "~/.xine";
00540         mkdir(cfg.c_str(), 755);
00541         cfg = cfg + "/config";
00542     }
00543     xine_config_load(this->xine, cfg.c_str());
00544 
00545     /* init xine */
00546     xine_init(this->xine);
00547 
00548     /* set verbosity */
00549     if(this->verbose)
00550         xine_engine_set_param(this->xine, XINE_PARAM_VERBOSITY, XINE_VERBOSITY_DEBUG);
00551     else
00552         xine_engine_set_param(this->xine, XINE_PARAM_VERBOSITY, XINE_VERBOSITY_NONE);
00553 }
00554 
00555 
00556 #endif
00557 
00558 
00559 bool MMSAV::onHandleInput(MMSWindow *window, MMSInputEvent *input) {
00560     // send the input event to the media backend
00561     return sendEvent(input);
00562 }
00563 
00564 /**
00565  * Initializes everything that is needed my MMSAV.
00566  *
00567  * First it initializes xine.
00568  * Then it sets some internal variables and does some surface
00569  * flipping.
00570  *
00571  * @param   verbose [in]    if true the xine engine writes debug messages to stdout
00572  * @param   window  [in]    window that will be used for video output
00573  *
00574  * @see MMSAV::xineInit()
00575  *
00576  * @exception   MMSAVError  Cannot get a new xine object
00577  * @exception   MMSAVError  MMSFBSurface::clear() failed
00578  * @exception   MMSAVError  MMSFBSurface::flip() failed
00579  * @exception   MMSAVError  Cannot open the DFB video driver
00580  */
00581 void MMSAV::initialize(const bool verbose, MMSWindow *window) {
00582     this->verbose          = verbose;
00583     this->window           = window;
00584 
00585     onHandleInputConnection.disconnect();
00586     if (window)
00587         onHandleInputConnection = window->onHandleInput->connect(sigc::mem_fun(this,&MMSAV::onHandleInput));
00588 
00589 
00590     if (this->backend == MMSMEDIA_BE_GST) {
00591 #ifdef __HAVE_GSTREAMER__
00592         // nothing to do, because the pipe will be created when starting playback
00593         // and then we have only to put keyboard, mouse, touchscreen events to the pipe
00594 #endif
00595     }
00596     else {
00597 #ifdef __HAVE_XINE__
00598 
00599     DEBUGMSG("MMSMedia", "xineInit()...");
00600 
00601     /* initialize xine */
00602     xineInit();
00603 
00604 
00605     DEBUGMSG("MMSMedia", "xineInit() done.");
00606 
00607     memset(&this->userd, 0, sizeof(this->userd));
00608 
00609     if (mmsfb->getBackend() != MMSFB_BE_DFB) {
00610         this->rawvisual.raw_output_cb = raw_frame_cb;
00611         this->rawvisual.supported_formats = XINE_VORAW_YV12;
00612         if(window) {
00613             this->rawvisual.user_data = (void *)&(this->userd);
00614             this->rawvisual.raw_overlay_cb = raw_overlay_cb;
00615         } else {
00616             this->rawvisual.user_data = NULL;
00617         }
00618     }
00619     else {
00620 #ifdef __HAVE_DIRECTFB__
00621         this->vodesc.format    = DSPF_UNKNOWN;
00622         this->vodesc.ratio     = 1.25;
00623         this->vodesc.width     = 720;
00624         this->vodesc.height    = 576;
00625         this->vodesc.rect.x    = 0;
00626         this->vodesc.rect.y    = 0;
00627 
00628         if(window) {
00629             window->getSurface()->getSize(&(this->vodesc.windsc.width), &(this->vodesc.windsc.height));
00630             this->vodesc.winsurface = window->getSurface();
00631             if(!this->vodesc.winsurface->clear())
00632                 THROW_DFB_ERROR(dfbres, "MMSFBSurface::clear() failed");
00633             if(!this->vodesc.winsurface->flip())
00634                 THROW_DFB_ERROR(dfbres, "MMSFBSurface::flip() failed");
00635         }
00636         this->vodesc.rect.w = this->vodesc.windsc.width;
00637         this->vodesc.rect.h = (int)((double)(this->vodesc.windsc.width) / this->vodesc.ratio + 0.5);
00638 #endif
00639     }
00640 
00641     //this->vodesc.winsurface
00642     /* clear surface */
00643 
00644     if (mmsfb->getBackend() != MMSFB_BE_DFB) {
00645         if(window) {
00646             this->userd.surf=window->getSurface();
00647             this->userd.surf->setBlittingFlags(MMSFB_BLIT_ANTIALIASING);
00648             this->userd.surf->getPixelFormat(&this->userd.surf_pixelformat);
00649             int w,h;
00650             this->userd.surf->getSize(&w,&h);
00651             this->userd.size.x=0;
00652             this->userd.size.y=0;
00653             this->userd.size.w=w;
00654             this->userd.size.h=h;
00655             this->userd.lastaspect=0.0;
00656             this->userd.interim = NULL;
00657             this->userd.overlayInterim = NULL;
00658             this->userd.numOverlays = 0;
00659             this->userd.overlays = NULL;
00660         }
00661         DEBUGMSG("MMSMedia", "opening video driver...");
00662         /* open the video output driver */
00663         if (!(this->vo = xine_open_video_driver(this->xine, "raw",
00664                                     XINE_VISUAL_TYPE_RAW, (void*) &this->rawvisual)))
00665             throw MMSAVError(0, "Cannot open the XINE RAW video driver");
00666     }
00667     else {
00668 #ifdef __HAVE_DIRECTFB__
00669             if(window) {
00670                 if(((IDirectFBSurface *)vodesc.winsurface->getDFBSurface())->SetBlittingFlags((IDirectFBSurface *)vodesc.winsurface->getDFBSurface(), DSBLIT_NOFX) != DFB_OK)
00671                     DEBUGMSG("MMSMedia", "set blitting failed");
00672                 /* fill the visual structure for the video output driver */
00673                 this->visual.destination  = (IDirectFBSurface *)vodesc.winsurface->getDFBSurface();
00674             }
00675             else
00676                 this->visual.destination = NULL;
00677             this->visual.subpicture   = NULL;
00678             this->visual.output_cb    = dfb_output_cb;
00679             this->visual.output_cdata = (void*) &(this->vodesc);
00680             this->visual.frame_cb     = dfb_frame_cb;
00681             this->visual.frame_cdata  = (void*) &(this->vodesc);
00682             //this->visual.destination->SetField( this->visual.destination, 0 );
00683             DEBUGMSG("MMSMedia", "opening video driver...");
00684             if (!(this->vo = xine_open_video_driver(this->xine, "DFB",
00685                                         XINE_VISUAL_TYPE_DFB, (void*) &this->visual)))
00686                         throw MMSAVError(0, "Cannot open the DFB video driver, please install directfb extras!");
00687 #endif
00688     }
00689     DEBUGMSG("MMSMedia", "opening video driver done.");
00690 
00691 
00692     /* open the audio output driver */
00693     const char* const *ao_list;
00694     int i = 0;
00695     if(!(ao_list = xine_list_audio_output_plugins(this->xine)) || !*ao_list) {
00696         DEBUGMSG("MMSMedia", "No audio output plugins found");
00697         xine_engine_set_param(this->xine, XINE_PARAM_IGNORE_AUDIO, 1);
00698         this->ao=NULL;
00699         return;
00700     }
00701     do {
00702         DEBUGMSG("MMSMedia", "checking audio output '%s'...", ao_list[i]);
00703 
00704         /* ignore file output */
00705         if(strcmp(ao_list[i], "file") == 0) {
00706             i++;
00707             continue;
00708         }
00709         else if(strcmp(ao_list[i], "none") == 0)
00710         {
00711             /* disable audio */
00712             xine_engine_set_param(this->xine, XINE_PARAM_IGNORE_AUDIO, 1);
00713             DEBUGMSG("MMSMedia", "Could not open audio driver, sound disabled!");
00714             break;
00715         }
00716 
00717         DEBUGMSG("MMSMedia", "opening audio output '%s'", ao_list[i]);
00718     }
00719     while(!(this->ao = xine_open_audio_driver(this->xine, ao_list[i++], NULL)));
00720 
00721     DEBUGMSG("MMSMedia", "Using audio driver '%s'", ao_list[i-1]);
00722 
00723 #endif
00724     }
00725 }
00726 
00727 
00728 
00729 /**
00730  * Constructor
00731  *
00732  * Initializes private variables
00733  *
00734  * @note    It checks the chosen backend against the
00735  *          supported ones. It simply switches the
00736  *          support, because one of the backends has
00737  *          to be implemented, otherwise mmsmedia
00738  *          isn't build.
00739  */
00740 MMSAV::MMSAV(MMSMEDIABackend _backend) :
00741     backend(_backend),
00742     window(NULL),
00743     surface(NULL),
00744     verbose(false),
00745     status(STATUS_NONE),
00746     pos(0)
00747 #ifdef __HAVE_XINE__
00748     , xine(NULL)
00749     , vo(NULL)
00750     , ao(NULL)
00751     , stream(NULL)
00752     , queue(NULL)
00753 #endif
00754 {
00755 
00756     this->onError          = new sigc::signal<void, string>;
00757     this->onStatusChange   = new sigc::signal<void, const unsigned short, const unsigned short>;
00758 
00759     switch(this->backend) {
00760         case MMSMEDIA_BE_GST:
00761 #ifdef __HAVE_GSTREAMER__
00762             gst_diskovideosink_data.uri = "";
00763             gst_diskovideosink_data.pipeline = NULL;
00764             break;
00765 #else
00766             cerr << "MMSAV: Disko was build without gstreamer support. Switching to xine." << endl;
00767             this->backend = MMSMEDIA_BE_XINE;
00768             break;
00769 #endif
00770         case MMSMEDIA_BE_XINE:
00771 #ifdef __HAVE_XINE__
00772             pthread_mutex_init(&this->lock, NULL);
00773 #else
00774             cerr << "MMSAV: Disko was build without xine support. Switching to gstreamer." << endl;
00775             this->backend = MMSMEDIA_BE_GST;
00776             break;
00777 #endif
00778         default:
00779             // shouldn't be reached
00780             break;
00781     }
00782 }
00783 
00784 /**
00785  * Destructor
00786  *
00787  * Deletes sigc++-callbacks and closes all xine related
00788  * stuff.
00789  */
00790 MMSAV::~MMSAV() {
00791     onHandleInputConnection.disconnect();
00792 
00793     if(this->onError) {
00794         this->onError->clear();
00795         delete this->onError;
00796     }
00797 
00798     if(this->onStatusChange) {
00799         this->onStatusChange->clear();
00800         delete this->onStatusChange;
00801     }
00802 
00803     if (this->backend == MMSMEDIA_BE_GST) {
00804 #ifdef __HAVE_GSTREAMER__
00805         mmsGstFree();
00806 #endif
00807     }
00808     else {
00809 #ifdef __HAVE_XINE__
00810         pthread_mutex_destroy(&this->lock);
00811 
00812 
00813         if(this->queue)
00814             xine_event_dispose_queue(this->queue);
00815         if(this->stream)
00816             xine_dispose(this->stream);
00817         if(this->ao)
00818             xine_close_audio_driver(this->xine, this->ao);
00819         if(this->vo)
00820             xine_close_video_driver(this->xine, this->vo);
00821 
00822         // dispose all registered post plugins
00823         map<string, xine_post_t*>::const_iterator i;
00824         for(i = audioPostPlugins.begin(); i != audioPostPlugins.end(); ++i)
00825             xine_post_dispose(this->xine, i->second);
00826         audioPostPlugins.erase(audioPostPlugins.begin(), audioPostPlugins.end());
00827 
00828         for(i = videoPostPlugins.begin(); i != videoPostPlugins.end(); ++i)
00829             xine_post_dispose(this->xine, i->second);
00830         videoPostPlugins.erase(videoPostPlugins.begin(), videoPostPlugins.end());
00831 
00832         // exit xine
00833         xine_exit(this->xine);
00834 
00835         if (this->userd.interim) {
00836             // delete interim (used for xine raw callback)
00837             delete this->userd.interim;
00838         }
00839 
00840         if (this->userd.overlayInterim) {
00841             // delete overlay interim (used for xine raw callback)
00842             delete this->userd.overlayInterim;
00843         }
00844 #endif
00845     }
00846 }
00847 
00848 #ifdef __HAVE_XINE__
00849 
00850 
00851 
00852 /**
00853  * Opens an audio/video object.
00854  *
00855  * It creates the xine stream, wires all registered
00856  * audio/video post plugins, sets the verbosity and
00857  * registers the event queue if given.
00858  *
00859  * @note    You have to register post plugins before
00860  * calling open().
00861  *
00862  * @param   queue_cb    [in]    xine event queue callback
00863  * @param   userData    [in]    data to be used in xine event callbacks
00864  *
00865  * @see MMSAV::registerAudioPostPlugin
00866  * @see MMSAV::registerVideoPostPlugin
00867  *
00868  * @exception   MMSAVError  Cannot get a new stream
00869  */
00870 void MMSAV::xineOpen(xine_event_listener_cb_t queue_cb, void *userData) {
00871     if(this->stream) {
00872         DEBUGMSG("MMSAV", "xine stream already present, skipping xineOpen");
00873         return;
00874     }
00875 
00876     /* open stream */
00877     if (!(this->stream = xine_stream_new(this->xine, this->ao, this->vo)))
00878         throw MMSAVError(0, "Cannot get a new stream");
00879 
00880     /* wire all post plugins */
00881     for(map<string, xine_post_t*>::const_iterator i = videoPostPlugins.begin(); i != videoPostPlugins.end(); ++i)
00882         xine_post_wire_video_port(xine_get_video_source(stream), i->second->video_input[0]);
00883     for(map<string, xine_post_t*>::const_iterator i = audioPostPlugins.begin(); i != audioPostPlugins.end(); ++i)
00884         xine_post_wire_audio_port(xine_get_audio_source(stream), i->second->audio_input[0]);
00885 
00886     /* set verbosity */
00887     if(this->verbose)
00888         xine_set_param(this->stream, XINE_PARAM_VERBOSITY, XINE_VERBOSITY_DEBUG);
00889     else
00890         xine_set_param(this->stream, XINE_PARAM_VERBOSITY, XINE_VERBOSITY_NONE);
00891 
00892     /*if(this->vo)
00893          xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, false);
00894 */
00895     if(this->ao) {
00896         xine_set_param(this->stream, XINE_PARAM_AUDIO_MUTE, false);
00897         xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
00898     }
00899 
00900     /* create event listener thread */
00901     if(queue_cb) {
00902         this->queue = xine_event_new_queue(this->stream);
00903         if(this->queue)
00904             xine_event_create_listener_thread(this->queue, queue_cb, userData);
00905         else
00906             DEBUGMSG("MMSMedia", "Could not create event listener");
00907     }
00908 }
00909 
00910 #endif
00911 
00912 /**
00913  * Registers a xine audio post plugin.
00914  *
00915  * Post plugin will be initialized.
00916  *
00917  * @param   name    [in]    name of the post plugin
00918  *
00919  * @return  true if plugin could be initialized correctly
00920  */
00921 bool MMSAV::registerAudioPostPlugin(string name) {
00922     if (this->backend == MMSMEDIA_BE_GST) {
00923 #ifdef __HAVE_GSTREAMER__
00924         return true;
00925 #endif
00926     }
00927     else {
00928 #ifdef __HAVE_XINE__
00929         xine_post_t *p;
00930 
00931         if(!(p = xine_post_init(this->xine, name.c_str(), 1, &this->ao, NULL)))
00932             DEBUGMSG("MMSMedia", "Could not initialize audio post plugin %s", name.c_str());
00933         else {
00934             audioPostPlugins[name] = p;
00935             return true;
00936         }
00937 
00938         return false;
00939 #endif
00940     }
00941 
00942     throw MMSAVError(0, "MMSAV::registerAudioPostPlugin() called but media backend does not match supported backends");
00943 }
00944 
00945 /**
00946  * Registers a xine video post plugin.
00947  *
00948  * Post plugin will be initialized.
00949  *
00950  * @param   name    [in]    name of the post plugin
00951  *
00952  * @return  true if plugin could be initialized correctly
00953  */
00954 bool MMSAV::registerVideoPostPlugin(string name) {
00955     if (this->backend == MMSMEDIA_BE_GST) {
00956 #ifdef __HAVE_GSTREAMER__
00957         return true;
00958 #endif
00959     }
00960     else {
00961 #ifdef __HAVE_XINE__
00962         xine_post_t *p;
00963 
00964         if(!(p = xine_post_init(this->xine, name.c_str(), 1, NULL, &this->vo)))
00965             DEBUGMSG("MMSMedia", "Could not initialize video post plugin %s", name.c_str());
00966         else {
00967             videoPostPlugins[name] = p;
00968             return true;
00969         }
00970 
00971         return false;
00972 #endif
00973     }
00974 
00975     throw MMSAVError(0, "MMSAV::registerVideoPostPlugin() called but media backend does not match supported backends");
00976 }
00977 
00978 #ifdef __HAVE_XINE__
00979 /**
00980  * Sets post plugin parameter.
00981  *
00982  * @param   plugins     [in]    map of post plugins
00983  * @param   name        [in]    name of post plugin that will be affected
00984  * @param   parameter   [in]    parameter to set
00985  * @param   value       [in]    value for the parameter
00986  *
00987  * @return  true if the parameter could be set
00988  */
00989 bool MMSAV::setPostPluginParameter(map<string, xine_post_t*> plugins, string name, string parameter, string value) {
00990     xine_post_in_t              *postIn;
00991     xine_post_api_t             *postApi;
00992     xine_post_api_descr_t       *postApiDesc;
00993     xine_post_api_parameter_t   *postApiParam;
00994     char                        *data;
00995 
00996     // search for plugin
00997     if(!(postIn = (xine_post_in_t *)xine_post_input(plugins[name], "parameters"))) {
00998         DEBUGMSG("MMSMedia", "Could not set parameter for post plugin %s: Plugin not registered", name.c_str());
00999         return false;
01000     }
01001 
01002     postApi      = (xine_post_api_t *)postIn->data;
01003     postApiDesc  = postApi->get_param_descr();
01004     postApiParam = postApiDesc->parameter;
01005     data         = new char[postApiDesc->struct_size];
01006     postApi->get_parameters(plugins[name], (void*)data);
01007 
01008     while(postApiParam->type != POST_PARAM_TYPE_LAST)
01009     {
01010         if(strToUpr(string(postApiParam->name)) == strToUpr(parameter)) {
01011             if(postApiParam->type == POST_PARAM_TYPE_INT) {
01012                 int iValue = atoi(value.c_str());
01013 
01014                 // check if the name of an enumeration is used
01015                 if(iValue == 0 && value.at(0) != '0') {
01016                     for(int i = 0; postApiParam->enum_values[i]; i++) {
01017                         if(value == postApiParam->enum_values[i]) {
01018                             iValue = i;
01019                             break;
01020                         }
01021                     }
01022                 } else {
01023                     // check if value is out of range
01024                     if(iValue < postApiParam->range_min || iValue > postApiParam->range_max) {
01025                         DEBUGMSG("MMSMedia", "Could not set %s's %s to %s: Out of range", name.c_str(), parameter.c_str(), value.c_str());
01026                         return false;
01027                     }
01028                 }
01029 
01030                 // set value
01031                 *(int *)(data + postApiParam->offset) = iValue;
01032                 DEBUGMSG("MMSMedia", "%s: %s = %s", name.c_str(), parameter.c_str(), postApiParam->enum_values[*(int *)(data + postApiParam->offset)]);
01033             }
01034             else if(postApiParam->type == POST_PARAM_TYPE_DOUBLE) {
01035                 double dValue = atof(value.c_str());
01036 
01037                 // check if value is out of range
01038                 if(dValue < postApiParam->range_min || dValue > postApiParam->range_max) {
01039                     DEBUGMSG("MMSMedia", "Could not set %s's %s to %s: Out of range", name.c_str(), parameter.c_str(), value.c_str());
01040                     return false;
01041                 }
01042 
01043                 // set value
01044                *(double *)(data + postApiParam->offset) = dValue;
01045                DEBUGMSG("MMSMedia", "%s: %s = %s", name.c_str(), parameter.c_str(), value.c_str());
01046             }
01047             else if(postApiParam->type == POST_PARAM_TYPE_BOOL) {
01048                 bool bValue = false;
01049                 if(value == "1" || strToUpr(value) == "TRUE")
01050                     bValue = true;
01051                *(bool *)(data + postApiParam->offset) = bValue;
01052                DEBUGMSG("MMSMedia", "%s: = %s", name.c_str(), parameter.c_str(), (bValue ? "true" : "false"));
01053             }
01054             else if(postApiParam->type == POST_PARAM_TYPE_CHAR) {
01055                 char cValue = value.at(0);
01056                *(char *)(data + postApiParam->offset) = cValue;
01057                DEBUGMSG("MMSMedia", "%s: %s = %c", name.c_str(), parameter.c_str(), cValue);
01058             }
01059             else if(postApiParam->type == POST_PARAM_TYPE_STRING) {
01060                 char *sValue = (char*)value.c_str();
01061                *(char **)(data + postApiParam->offset) = sValue;
01062                DEBUGMSG("MMSMedia", "%s: %s = %s", name.c_str(), parameter.c_str(), sValue);
01063             }
01064             break;
01065         }
01066         postApiParam++;
01067     }
01068 
01069     if(!postApi->set_parameters(plugins[name], (void *)data))
01070         DEBUGMSG("MMSMedia", "Error setting post plugin parameter");
01071 
01072     delete[] data;
01073 
01074     return true;
01075 }
01076 #endif
01077 
01078 /**
01079  * Sets audio post plugin parameter.
01080  *
01081  * @param   name        [in]    name of post plugin that will be affected
01082  * @param   parameter   [in]    parameter to set
01083  * @param   value       [in]    value for the parameter
01084  *
01085  * @return  true if the parameter could be set
01086  *
01087  * @see     MMSAV::setPostPluginParameter
01088  * @see     MMSAV::setVideoPostPluginParameter
01089  */
01090 bool MMSAV::setAudioPostPluginParameter(string name, string parameter, string value) {
01091     if (this->backend == MMSMEDIA_BE_GST) {
01092 #ifdef __HAVE_GSTREAMER__
01093         return true;
01094 #endif
01095     }
01096     else {
01097 #ifdef __HAVE_XINE__
01098         return setPostPluginParameter(this->audioPostPlugins, name, parameter, value);
01099 #endif
01100     }
01101 
01102     throw MMSAVError(0, "MMSAV::setAudioPostPluginParameter() called but media backend does not match supported backends");
01103 }
01104 
01105 /**
01106  * Sets video post plugin parameter.
01107  *
01108  * @param   name        [in]    name of post plugin that will be affected
01109  * @param   parameter   [in]    parameter to set
01110  * @param   value       [in]    value for the parameter
01111  *
01112  * @return  true if the parameter could be set
01113  *
01114  * @see     MMSAV::setPostPluginParameter
01115  * @see     MMSAV::setAudioPostPluginParameter
01116  */
01117 bool MMSAV::setVideoPostPluginParameter(string name, string parameter, string value) {
01118     if (this->backend == MMSMEDIA_BE_GST) {
01119 #ifdef __HAVE_GSTREAMER__
01120         return true;
01121 #endif
01122     }
01123     else {
01124 #ifdef __HAVE_XINE__
01125         return setPostPluginParameter(this->videoPostPlugins, name, parameter, value);
01126 #endif
01127     }
01128 
01129     throw MMSAVError(0, "MMSAV::setVideoPostPluginParameter() called but media backend does not match supported backends");
01130 }
01131 
01132 
01133 
01134 /**
01135  * Sets internal status of sound/video playback.
01136  *
01137  * It also emits a signal, which can be handled using the
01138  * sigc++ connectors.
01139  *
01140  * @param   status  [in]    status to set
01141  *
01142  * @see MMSAV::onStatusChange
01143  */
01144 void MMSAV::setStatus(int status) {
01145     switch(status) {
01146         case STATUS_PLAYING :
01147             if(this->status != this->STATUS_NONE)
01148                 this->onStatusChange->emit(this->status, status);
01149             this->status = status;
01150             return;
01151         case STATUS_PAUSED  :
01152         case STATUS_STOPPED :
01153         case STATUS_FFWD    :
01154         case STATUS_FFWD2   :
01155         case STATUS_SLOW    :
01156         case STATUS_SLOW2   :
01157             this->onStatusChange->emit(this->status, status);
01158             this->status = status;
01159             return;
01160         default:
01161             break;
01162     }
01163 
01164     this->onStatusChange->emit(status, status);
01165 }
01166 
01167 /**
01168  * Determines if a stream is currently being played.
01169  *
01170  * @return true if stream is being played
01171  */
01172 bool MMSAV::isPlaying() {
01173     switch(this->backend) {
01174         case MMSMEDIA_BE_GST:
01175 #ifdef __HAVE_GSTREAMER__
01176             return (this->status == STATUS_PLAYING);
01177 #endif
01178             break;
01179         case MMSMEDIA_BE_XINE:
01180 #ifdef __HAVE_XINE__
01181             if(this->status == STATUS_PLAYING) {
01182                 if(xine_get_status(this->stream)!=XINE_STATUS_PLAY) {
01183                     this->setStatus(STATUS_STOPPED);
01184                     return false;
01185                 }
01186                 else return true;
01187             }
01188             return false;
01189 #endif
01190             break;
01191         default:
01192             // shouldn't be reached
01193             break;
01194     }
01195 
01196     throw MMSAVError(0, "MMSAV::isPlaying() called but media backend does not match supported backends");
01197 }
01198 
01199 /**
01200  * Determines if a stream is currently being paused.
01201  *
01202  * @return true if stream is being paused
01203  */
01204 bool MMSAV::isPaused() {
01205     switch(this->backend) {
01206         case MMSMEDIA_BE_GST:
01207 #ifdef __HAVE_GSTREAMER__
01208             return false;
01209 #endif
01210             break;
01211         case MMSMEDIA_BE_XINE:
01212 #ifdef __HAVE_XINE__
01213             if(this->status == STATUS_PAUSED) {
01214                 if(xine_get_status(this->stream)!=XINE_STATUS_PLAY) {
01215                     this->setStatus(STATUS_STOPPED);
01216                     return false;
01217                 }
01218                 else return true;
01219             }
01220             return false;
01221 #endif
01222             break;
01223         default:
01224             // shouldn't be reached
01225             break;
01226     }
01227 
01228     throw MMSAVError(0, "MMSAV::isPaused() called but media backend does not match supported backends");
01229 }
01230 
01231 /**
01232  * Determines if a stream is in stopped status.
01233  *
01234  * @return true if stream is being stopped
01235  */
01236 bool MMSAV::isStopped() {
01237     return (this->status == STATUS_STOPPED);
01238 }
01239 
01240 /**
01241  * Starts playing.
01242  *
01243  * If the continue flag is set it tries to continue
01244  * at the position where it was stopped before.
01245  *
01246  * @param   mrl     [in]    mrl to play
01247  * @param   cont    [in]    if true it tries to continue at a position stopped before
01248  *
01249  * @exception   MMSAVError stream could not be opened
01250  */
01251 void MMSAV::startPlaying(const string mrl, const bool cont) {
01252     DEBUGMSG("MMSAV", "currentMRL: %s mrl: %s status: %d", currentMRL.c_str(), mrl.c_str(), status);
01253     if((currentMRL == mrl) && (this->status == this->STATUS_PLAYING)) return;
01254     this->currentMRL = mrl;
01255 
01256     if (this->backend == MMSMEDIA_BE_GST) {
01257 #ifdef __HAVE_GSTREAMER__
01258 
01259 
01260 //TODO:new version of MMSAV
01261 //TODO:version with playbin without disko video sink and without GST://
01262 
01263         // disable VIDEO LAYER - only for test
01264         MMSFBLayer *vl = mmsfbmanager.getVideoLayer();
01265         if (vl != mmsfbmanager.getGraphicsLayer())
01266             vl->releaseLayer();
01267 
01268 
01269 
01270         // init gst pipe
01271         this->gst_diskovideosink_data.pipeline = mmsGstInit(currentMRL, this->window->getSurface());
01272         if (!this->gst_diskovideosink_data.pipeline)
01273             return;
01274         this->gst_diskovideosink_data.uri = currentMRL;
01275 
01276         // play the pipe
01277         pthread_t thread;
01278         if(pthread_create(&thread, NULL, (void* (*)(void*))gstPlayRoutine, &this->gst_diskovideosink_data) == 0)
01279             pthread_detach(thread);
01280 
01281 #endif
01282     }
01283     else {
01284 #ifdef __HAVE_XINE__
01285 
01286         if(!this->stream) this->xineOpen();
01287 
01288         if(!cont) this->pos = 0;
01289 
01290         /* start playing in extra thread to avoid blocking the application */
01291         //pthread_t thread;
01292         internalStreamData *streamData = new internalStreamData;
01293         streamData->stream = this->stream;
01294         streamData->pos    = this->pos;
01295         streamData->status = &(this->status);
01296         streamData->mrl    = mrl.c_str();
01297         streamData->lock   = &(this->lock);
01298         /*if(pthread_create(&thread, NULL, xinePlayRoutine, streamData) == 0)
01299             pthread_detach(thread);
01300         else*/
01301             xinePlayRoutine(streamData);
01302 
01303 #endif
01304     }
01305 }
01306 
01307 /**
01308  * Continues playing.
01309  *
01310  * It only works if playing was stopped or speed
01311  * changed to other than normal.
01312  */
01313 void MMSAV::play() {
01314     switch(this->backend) {
01315         case MMSMEDIA_BE_GST:
01316 #ifdef __HAVE_GSTREAMER__
01317             return;
01318 #endif
01319             break;
01320         case MMSMEDIA_BE_XINE:
01321 #ifdef __HAVE_XINE__
01322             if(!this->stream) return;
01323 
01324             if(this->status == this->STATUS_PAUSED  ||
01325                this->status == this->STATUS_SLOW    ||
01326                this->status == this->STATUS_SLOW2   ||
01327                this->status == this->STATUS_FFWD    ||
01328                this->status == this->STATUS_FFWD2) {
01329                this->setStatus(this->STATUS_PLAYING);
01330                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
01331             }
01332             return;
01333 #endif
01334             break;
01335         default:
01336             // shouldn't be reached
01337             break;
01338     }
01339 
01340     throw MMSAVError(0, "MMSAV::play() called but media backend does not match supported backends");
01341 }
01342 
01343 /**
01344  * Stops playing.
01345  *
01346  * @param   savePosition    [in]    if true stream position will be saved for continuation
01347  *
01348  * It saves the position, so if you call MMSAV::play()
01349  * afterwards with the continue flag set, it will continue
01350  * at this position.
01351  */
01352 void MMSAV::stop(const bool savePosition) {
01353     switch(this->backend) {
01354         case MMSMEDIA_BE_GST:
01355 #ifdef __HAVE_GSTREAMER__
01356             return;
01357 #endif
01358             break;
01359         case MMSMEDIA_BE_XINE: {
01360 #ifdef __HAVE_XINE__
01361             if(!this->stream) return;
01362 
01363             /* save position */
01364             if(savePosition)
01365                 xine_get_pos_length(this->stream, &this->pos, NULL, NULL);
01366 
01367             /* stop xine in extra thread to avoid blocking the application */
01368             //pthread_t thread;
01369             internalStreamData *streamData = new internalStreamData;
01370             streamData->stream = this->stream;
01371             streamData->status = &(this->status);
01372             streamData->lock   = &(this->lock);
01373             /*if(pthread_create(&thread, NULL, stopRoutine, streamData) == 0)
01374                 pthread_detach(thread);
01375             else*/
01376                 stopRoutine(streamData);
01377             return;
01378 #endif
01379             break;
01380         }
01381         default:
01382             // shouldn't be reached
01383             break;
01384     }
01385 
01386     throw MMSAVError(0, "MMSAV::stop() called but media backend does not match supported backends");
01387 }
01388 
01389 /**
01390  * Pauses.
01391  *
01392  * It only works if stream is playing (can be slow,
01393  * ffwd etc.).
01394  */
01395 void MMSAV::pause() {
01396     switch(this->backend) {
01397         case MMSMEDIA_BE_GST:
01398 #ifdef __HAVE_GSTREAMER__
01399             return;
01400 #endif
01401             break;
01402         case MMSMEDIA_BE_XINE:
01403 #ifdef __HAVE_XINE__
01404             if(this->status == this->STATUS_PLAYING ||
01405                this->status == this->STATUS_SLOW    ||
01406                this->status == this->STATUS_SLOW2   ||
01407                this->status == this->STATUS_FFWD    ||
01408                this->status == this->STATUS_FFWD2) {
01409                this->setStatus(this->STATUS_PAUSED);
01410                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
01411                 xine_set_param(this->stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
01412             }
01413             return;
01414 #endif
01415             break;
01416         default:
01417             // shouldn't be reached
01418             break;
01419     }
01420 
01421     throw MMSAVError(0, "MMSAV::pause() called but media backend does not match supported backends");
01422 }
01423 
01424 /**
01425  * Playback will be switched to slow motion.
01426  *
01427  * There are two different speed settings for slow motion.
01428  * Twice as slow and four times as slow.
01429  *
01430  * @see MMSAV::ffwd()
01431  * @see MMSAV::rewind()
01432  */
01433 void MMSAV::slow() {
01434     switch(this->backend) {
01435         case MMSMEDIA_BE_GST:
01436 #ifdef __HAVE_GSTREAMER__
01437             return;
01438 #endif
01439             break;
01440         case MMSMEDIA_BE_XINE:
01441 #ifdef __HAVE_XINE__
01442             if(this->status == this->STATUS_PLAYING || this->status == this->STATUS_PAUSED) {
01443                 this->setStatus(this->STATUS_SLOW);
01444                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_2);
01445             }
01446             else if(this->status == this->STATUS_SLOW) {
01447                 this->setStatus(this->STATUS_SLOW2);
01448                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_4);
01449             }
01450             else if(this->status == this->STATUS_FFWD) {
01451                 this->setStatus(this->STATUS_PLAYING);
01452                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
01453             }
01454             else if(this->status == this->STATUS_FFWD2) {
01455                 this->setStatus(this->STATUS_FFWD);
01456                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_FAST_2);
01457             }
01458             return;
01459 #endif
01460             break;
01461         default:
01462             // shouldn't be reached
01463             break;
01464     }
01465 
01466     throw MMSAVError(0, "MMSAV::slow() called but media backend does not match supported backends");
01467 }
01468 
01469 /**
01470  * Playback will be switched to fast forward.
01471  *
01472  * There are two different speed settings for fast forward.
01473  * Twice as fast and four times as fast.
01474  *
01475  * @see MMSAV::slow()
01476  * @see MMSAV::rewind()
01477  */
01478 void MMSAV::ffwd() {
01479     switch(this->backend) {
01480         case MMSMEDIA_BE_GST:
01481 #ifdef __HAVE_GSTREAMER__
01482 
01483 
01484             printf("ffwd-------------------------------------\n");
01485 
01486 
01487 /*
01488 static void
01489 seek_to_time (GstElement *pipeline,
01490           gint64      time_nanoseconds)
01491 {
01492   if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
01493                          GST_SEEK_TYPE_SET, time_nanoseconds,
01494                          GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
01495     g_print ("Seek failed!\n");
01496   }
01497 }
01498 
01499  */
01500 /*
01501             gst_element_seek(this->gst_diskovideosink_data.player,
01502                     1.0,
01503                     GST_FORMAT_TIME,
01504                     GST_SEEK_FLAG_FLUSH,
01505                     GST_SEEK_TYPE_SET,
01506                     1000*1000*1000,
01507                     GST_SEEK_TYPE_NONE,
01508                     GST_CLOCK_TIME_NONE);*/
01509                              /*
01510                                                                      gdouble rate,
01511                                                                      GstFormat format,
01512                                                                      GstSeekFlags flags,
01513                                                                      GstSeekType cur_type,
01514                                                                      gint64 cur,
01515                                                                      GstSeekType stop_type,
01516                                                                      gint64 stop);*/
01517 
01518             return;
01519 #endif
01520             break;
01521         case MMSMEDIA_BE_XINE:
01522 #ifdef __HAVE_XINE__
01523             if(this->status == this->STATUS_PLAYING || this->status == this->STATUS_PAUSED) {
01524                 this->setStatus(this->STATUS_FFWD);
01525                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_FAST_2);
01526             }
01527             else if(this->status == this->STATUS_FFWD) {
01528                 this->setStatus(this->STATUS_FFWD2);
01529                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_FAST_4);
01530             }
01531             else if(this->status == this->STATUS_SLOW) {
01532                 this->setStatus(this->STATUS_PLAYING);
01533                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
01534             }
01535             else if(this->status == this->STATUS_SLOW2) {
01536                 this->setStatus(this->STATUS_SLOW);
01537                 xine_set_param(this->stream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_2);
01538             }
01539             return;
01540 #endif
01541             break;
01542         default:
01543             // shouldn't be reached
01544             break;
01545     }
01546 
01547     throw MMSAVError(0, "MMSAV::ffwd() called but media backend does not match supported backends");
01548 }
01549 
01550 /**
01551  * Gets information about the length of the actual title
01552  * and the time of the current position in seconds.
01553  *
01554  * @param   pos     [out]   time in seconds of current position
01555  * @param   length  [out]   time in seconds of title length
01556  */
01557 bool MMSAV::getTimes(int *pos, int *length) {
01558     switch(this->backend) {
01559         case MMSMEDIA_BE_GST:
01560 #ifdef __HAVE_GSTREAMER__
01561             return 0;
01562 #endif
01563             break;
01564         case MMSMEDIA_BE_XINE:
01565 #ifdef __HAVE_XINE__
01566             if(!this->stream || !xine_get_pos_length(this->stream, NULL, pos, length)) return false;
01567 
01568             if(pos)    (*pos)    /= 1000;
01569             if(length) (*length) /= 1000;
01570             return true;
01571 #endif
01572             break;
01573         default:
01574             // shouldn't be reached
01575             break;
01576     }
01577 
01578     throw MMSAVError(0, "MMSAV::getTimes() called but media backend does not match supported backends");
01579 }
01580 
01581 /**
01582  * Sets the brightness if video output is done.
01583  *
01584  * @param   count   [in]    amount of brightness
01585  *
01586  * @see     MMSAV::brightnessUp()
01587  * @see     MMSAV::brightnessDown()
01588  */
01589 void MMSAV::setBrightness(int count) {
01590     switch(this->backend) {
01591         case MMSMEDIA_BE_GST:
01592 #ifdef __HAVE_GSTREAMER__
01593             return;
01594 #endif
01595             break;
01596         case MMSMEDIA_BE_XINE:
01597 #ifdef __HAVE_XINE__
01598             if(this->vo)
01599                 xine_set_param(this->stream, XINE_PARAM_VO_BRIGHTNESS, count);
01600             return;
01601 #endif
01602             break;
01603         default:
01604             // shouldn't be reached
01605             break;
01606     }
01607 
01608     throw MMSAVError(0, "MMSAV::setBrightness() called but media backend does not match supported backends");
01609 }
01610 
01611 /**
01612  * Increases the brightness if video output is done.
01613  *
01614  * @param   count   [in]    amount of brightness to increase
01615  *
01616  * @see     MMSAV::setBrightness()
01617  * @see     MMSAV::brightnessDown()
01618  */
01619 void MMSAV::brightnessUp(int count) {
01620     switch(this->backend) {
01621         case MMSMEDIA_BE_GST:
01622 #ifdef __HAVE_GSTREAMER__
01623             return;
01624 #endif
01625             break;
01626         case MMSMEDIA_BE_XINE:
01627 #ifdef __HAVE_XINE__
01628             if(this->vo) {
01629                 int value = xine_get_param(this->stream, XINE_PARAM_VO_BRIGHTNESS);
01630                 xine_set_param(this->stream, XINE_PARAM_VO_BRIGHTNESS, value + count*500);
01631             }
01632             return;
01633 #endif
01634             break;
01635         default:
01636             // shouldn't be reached
01637             break;
01638     }
01639 
01640     throw MMSAVError(0, "MMSAV::brightnessUp() called but media backend does not match supported backends");
01641 }
01642 
01643 /**
01644  * Decreases the brightness if video output is done.
01645  *
01646  * @param   count   [in]    amount of brightness to decrease
01647  *
01648  * @see     MMSAV::setBrightness()
01649  * @see     MMSAV::brightnessUp()
01650  */
01651 void MMSAV::brightnessDown(int count) {
01652     switch(this->backend) {
01653         case MMSMEDIA_BE_GST:
01654 #ifdef __HAVE_GSTREAMER__
01655             return;
01656 #endif
01657             break;
01658         case MMSMEDIA_BE_XINE:
01659 #ifdef __HAVE_XINE__
01660             if(this->vo) {
01661                 int value = xine_get_param(this->stream, XINE_PARAM_VO_BRIGHTNESS);
01662                 xine_set_param(this->stream, XINE_PARAM_VO_BRIGHTNESS, value - count*500);
01663             }
01664             return;
01665 #endif
01666             break;
01667         default:
01668             // shouldn't be reached
01669             break;
01670     }
01671 
01672     throw MMSAVError(0, "MMSAV::brightnessDown() called but media backend does not match supported backends");
01673 }
01674 
01675 /**
01676  * Sets the contrast if video output is done.
01677  *
01678  * @param   count   [in]    amount of contrast
01679  *
01680  * @see     MMSAV::contrastUp()
01681  * @see     MMSAV::contrastDown()
01682  */
01683 void MMSAV::setContrast(int count) {
01684     switch(this->backend) {
01685         case MMSMEDIA_BE_GST:
01686 #ifdef __HAVE_GSTREAMER__
01687             return;
01688 #endif
01689             break;
01690         case MMSMEDIA_BE_XINE:
01691 #ifdef __HAVE_XINE__
01692             if(this->vo)
01693                 xine_set_param(this->stream, XINE_PARAM_VO_CONTRAST, count);
01694             return;
01695 #endif
01696             break;
01697         default:
01698             // shouldn't be reached
01699             break;
01700     }
01701 
01702     throw MMSAVError(0, "MMSAV::setContrast() called but media backend does not match supported backends");
01703 }
01704 
01705 /**
01706  * Increases the contrast if video output is done.
01707  *
01708  * @param   count   [in]    amount of contrast to increase
01709  *
01710  * @see     MMSAV::setContrast()
01711  * @see     MMSAV::contrastDown()
01712  */
01713 void MMSAV::contrastUp(int count) {
01714     switch(this->backend) {
01715         case MMSMEDIA_BE_GST:
01716 #ifdef __HAVE_GSTREAMER__
01717             return;
01718 #endif
01719             break;
01720         case MMSMEDIA_BE_XINE:
01721 #ifdef __HAVE_XINE__
01722             if(this->vo) {
01723                 int value = xine_get_param(this->stream, XINE_PARAM_VO_CONTRAST);
01724                 xine_set_param(this->stream, XINE_PARAM_VO_CONTRAST, value + count*500);
01725             }
01726             return;
01727 #endif
01728             break;
01729         default:
01730             // shouldn't be reached
01731             break;
01732     }
01733 
01734     throw MMSAVError(0, "MMSAV::contrastUp() called but media backend does not match supported backends");
01735 }
01736 
01737 /**
01738  * Decreases the contrast if video output is done.
01739  *
01740  * @param   count   [in]    amount of contrast to decrease
01741  *
01742  * @see     MMSAV::setContrast()
01743  * @see     MMSAV::contrastUp()
01744  */
01745 void MMSAV::contrastDown(int count) {
01746     switch(this->backend) {
01747         case MMSMEDIA_BE_GST:
01748 #ifdef __HAVE_GSTREAMER__
01749             return;
01750 #endif
01751             break;
01752         case MMSMEDIA_BE_XINE:
01753 #ifdef __HAVE_XINE__
01754             if(this->vo) {
01755                 int value = xine_get_param(this->stream, XINE_PARAM_VO_CONTRAST);
01756                 xine_set_param(this->stream, XINE_PARAM_VO_CONTRAST, value - count*500);
01757             }
01758             return;
01759 #endif
01760             break;
01761         default:
01762             // shouldn't be reached
01763             break;
01764     }
01765 
01766     throw MMSAVError(0, "MMSAV::contrastDown() called but media backend does not match supported backends");
01767 }
01768 
01769 /**
01770  * Sets the saturation if video output is done.
01771  *
01772  * @param   count   [in]    amount of saturation
01773  *
01774  * @see     MMSAV::saturationUp()
01775  * @see     MMSAV::saturationDown()
01776  */
01777 void MMSAV::setSaturation(int count) {
01778     switch(this->backend) {
01779         case MMSMEDIA_BE_GST:
01780 #ifdef __HAVE_GSTREAMER__
01781             return;
01782 #endif
01783             break;
01784         case MMSMEDIA_BE_XINE:
01785 #ifdef __HAVE_XINE__
01786             if(this->vo)
01787                 xine_set_param(this->stream, XINE_PARAM_VO_SATURATION, count);
01788             return;
01789 #endif
01790             break;
01791         default:
01792             // shouldn't be reached
01793             break;
01794     }
01795 
01796     throw MMSAVError(0, "MMSAV::setSaturation() called but media backend does not match supported backends");
01797 }
01798 
01799 /**
01800  * Increases the saturation if video output is done.
01801  *
01802  * @param   count   [in]    amount of saturation to increase
01803  *
01804  * @see     MMSAV::setSaturation()
01805  * @see     MMSAV::saturationDown()
01806  */
01807 void MMSAV::saturationUp(int count) {
01808     switch(this->backend) {
01809         case MMSMEDIA_BE_GST:
01810 #ifdef __HAVE_GSTREAMER__
01811             return;
01812 #endif
01813             break;
01814         case MMSMEDIA_BE_XINE:
01815 #ifdef __HAVE_XINE__
01816             if(this->vo) {
01817                 int value = xine_get_param(this->stream, XINE_PARAM_VO_SATURATION);
01818                 xine_set_param(this->stream, XINE_PARAM_VO_SATURATION, value + count*500);
01819             }
01820             return;
01821 #endif
01822             break;
01823         default:
01824             // shouldn't be reached
01825             break;
01826     }
01827 
01828     throw MMSAVError(0, "MMSAV::saturationUp() called but media backend does not match supported backends");
01829 }
01830 
01831 /**
01832  * Decreases the saturation if video output is done.
01833  *
01834  * @param   count   [in]    amount of saturation to decrease
01835  *
01836  * @see     MMSAV::setSaturation()
01837  * @see     MMSAV::saturationUp()
01838  */
01839 void MMSAV::saturationDown(int count) {
01840     switch(this->backend) {
01841         case MMSMEDIA_BE_GST:
01842 #ifdef __HAVE_GSTREAMER__
01843             return;
01844 #endif
01845             break;
01846         case MMSMEDIA_BE_XINE:
01847 #ifdef __HAVE_XINE__
01848             if(this->vo) {
01849                 int value = xine_get_param(this->stream, XINE_PARAM_VO_SATURATION);
01850                 xine_set_param(this->stream, XINE_PARAM_VO_SATURATION, value - count*500);
01851             }
01852             return;
01853 #endif
01854             break;
01855         default:
01856             // shouldn't be reached
01857             break;
01858     }
01859 
01860     throw MMSAVError(0, "MMSAV::saturationDown() called but media backend does not match supported backends");
01861 }
01862 
01863 /**
01864  * Sets the hue if video output is done.
01865  *
01866  * @param   count   [in]    amount of hue
01867  *
01868  * @see     MMSAV::hueUp()
01869  * @see     MMSAV::hueDown()
01870  */
01871 void MMSAV::setHue(int count) {
01872     switch(this->backend) {
01873         case MMSMEDIA_BE_GST:
01874 #ifdef __HAVE_GSTREAMER__
01875             return;
01876 #endif
01877             break;
01878         case MMSMEDIA_BE_XINE:
01879 #ifdef __HAVE_XINE__
01880             if(this->vo)
01881                 xine_set_param(this->stream, XINE_PARAM_VO_HUE, count);
01882             return;
01883 #endif
01884             break;
01885         default:
01886             // shouldn't be reached
01887             break;
01888     }
01889 
01890     throw MMSAVError(0, "MMSAV::setHue() called but media backend does not match supported backends");
01891 }
01892 
01893 /**
01894  * Increases the hue if video output is done.
01895  *
01896  * @param   count   [in]    amount of hue to increase
01897  *
01898  * @see     MMSAV::setHue()
01899  * @see     MMSAV::hueDown()
01900  */
01901 void MMSAV::hueUp(int count) {
01902     switch(this->backend) {
01903         case MMSMEDIA_BE_GST:
01904 #ifdef __HAVE_GSTREAMER__
01905             return;
01906 #endif
01907             break;
01908         case MMSMEDIA_BE_XINE:
01909 #ifdef __HAVE_XINE__
01910             if(this->vo) {
01911                 int value = xine_get_param(this->stream, XINE_PARAM_VO_HUE);
01912                 xine_set_param(this->stream, XINE_PARAM_VO_HUE, value + count*500);
01913             }
01914             return;
01915 #endif
01916             break;
01917         default:
01918             // shouldn't be reached
01919             break;
01920     }
01921 
01922     throw MMSAVError(0,"MMSAV::hueUp() called but media backend does not match supported backends");
01923 }
01924 
01925 /**
01926  * Decreases the hue if video output is done.
01927  *
01928  * @param   count   [in]    amount of hue to decrease
01929  *
01930  * @see     MMSAV::setHue()
01931  * @see     MMSAV::hueUp()
01932  */
01933 void MMSAV::hueDown(int count) {
01934     switch(this->backend) {
01935         case MMSMEDIA_BE_GST:
01936 #ifdef __HAVE_GSTREAMER__
01937             return;
01938 #endif
01939             break;
01940         case MMSMEDIA_BE_XINE:
01941 #ifdef __HAVE_XINE__
01942             if(this->vo) {
01943                 int value = xine_get_param(this->stream, XINE_PARAM_VO_HUE);
01944                 xine_set_param(this->stream, XINE_PARAM_VO_HUE, value - count*500);
01945             }
01946             return;
01947 #endif
01948             break;
01949         default:
01950             // shouldn't be reached
01951             break;
01952     }
01953 
01954     throw MMSAVError(0, "MMSAV::hueDown() called but media backend does not match supported backends");
01955 }
01956 
01957 /**
01958  * Sets the volume of the audio output.
01959  *
01960  * @param   percent [in]    volume in percent
01961  */
01962 void MMSAV::setVolume(int percent) {
01963     switch(this->backend) {
01964         case MMSMEDIA_BE_GST:
01965 #ifdef __HAVE_GSTREAMER__
01966             return;
01967 #endif
01968             break;
01969         case MMSMEDIA_BE_XINE:
01970 #ifdef __HAVE_XINE__
01971             if(this->ao)
01972                 xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, percent);
01973             return;
01974 #endif
01975             break;
01976         default:
01977             // shouldn't be reached
01978             break;
01979     }
01980 
01981     throw MMSAVError(0, "MMSAV::setVolume() called but media backend does not match supported backends");
01982 }
01983 
01984 /**
01985  * Send a xine event to the engine
01986  *
01987  * @param   type    [in]    type of event
01988  * @param   data    [in]    event specific data
01989  * @param   datalen [in]    length of data
01990  */
01991 void MMSAV::sendEvent(int type, void *data, int datalen) {
01992     switch(this->backend) {
01993         case MMSMEDIA_BE_GST:
01994 #ifdef __HAVE_GSTREAMER__
01995             return;
01996 #endif
01997             break;
01998         case MMSMEDIA_BE_XINE:
01999 #ifdef __HAVE_XINE__
02000             xine_event_t evt;
02001 
02002             evt.stream      = this->stream;
02003             evt.data        = data;
02004             evt.data_length = datalen;
02005             evt.type        = type;
02006             xine_event_send(this->stream, &evt);
02007             return;
02008 #endif
02009             break;
02010         default:
02011             // shouldn't be reached
02012             break;
02013     }
02014 
02015     throw MMSAVError(0, "MMSAV::sendEvent() called but media backend does not match supported backends");
02016 }
02017 
02018 
02019 bool MMSAV::sendKeyPress(MMSKeySymbol key) {
02020     switch(this->backend) {
02021     case MMSMEDIA_BE_GST: {
02022 #ifdef __HAVE_GSTREAMER__
02023         return mmsGstSendKeyPress(gst_diskovideosink_data.pipeline, key);
02024 #endif
02025         break;
02026     }
02027     case MMSMEDIA_BE_XINE:
02028 #ifdef __HAVE_XINE__
02029         return false;
02030 #endif
02031         break;
02032     default:
02033         // shouldn't be reached
02034         break;
02035     }
02036 
02037     throw MMSAVError(0, "MMSAV::sendKeyPress() called but media backend does not match supported backends");
02038 
02039     return false;
02040 }
02041 
02042 bool MMSAV::sendKeyRelease(MMSKeySymbol key) {
02043     switch(this->backend) {
02044     case MMSMEDIA_BE_GST: {
02045 #ifdef __HAVE_GSTREAMER__
02046         return mmsGstSendKeyRelease(gst_diskovideosink_data.pipeline, key);
02047 #endif
02048         break;
02049     }
02050     case MMSMEDIA_BE_XINE:
02051 #ifdef __HAVE_XINE__
02052         return false;
02053 #endif
02054         break;
02055     default:
02056         // shouldn't be reached
02057         break;
02058     }
02059 
02060     throw MMSAVError(0, "MMSAV::sendKeyRelease() called but media backend does not match supported backends");
02061 
02062     return false;
02063 }
02064 
02065 bool MMSAV::sendButtonPress(int posx, int posy) {
02066     switch(this->backend) {
02067     case MMSMEDIA_BE_GST: {
02068 #ifdef __HAVE_GSTREAMER__
02069         return mmsGstSendButtonPress(gst_diskovideosink_data.pipeline, posx, posy);
02070 #endif
02071         break;
02072     }
02073     case MMSMEDIA_BE_XINE:
02074 #ifdef __HAVE_XINE__
02075         return false;
02076 #endif
02077         break;
02078     default:
02079         // shouldn't be reached
02080         break;
02081     }
02082 
02083     throw MMSAVError(0, "MMSAV::sendButtonPress() called but media backend does not match supported backends");
02084 
02085     return false;
02086 }
02087 
02088 bool MMSAV::sendButtonRelease(int posx, int posy) {
02089     switch(this->backend) {
02090     case MMSMEDIA_BE_GST: {
02091 #ifdef __HAVE_GSTREAMER__
02092         return mmsGstSendButtonRelease(gst_diskovideosink_data.pipeline, posx, posy);
02093 #endif
02094         break;
02095     }
02096     case MMSMEDIA_BE_XINE:
02097 #ifdef __HAVE_XINE__
02098         return false;
02099 #endif
02100         break;
02101     default:
02102         // shouldn't be reached
02103         break;
02104     }
02105 
02106     throw MMSAVError(0, "MMSAV::sendButtonRelease() called but media backend does not match supported backends");
02107 
02108     return false;
02109 }
02110 
02111 bool MMSAV::sendAxisMotion(int posx, int posy) {
02112     switch(this->backend) {
02113     case MMSMEDIA_BE_GST: {
02114 #ifdef __HAVE_GSTREAMER__
02115         return mmsGstSendAxisMotion(gst_diskovideosink_data.pipeline, posx, posy);
02116 #endif
02117         break;
02118     }
02119     case MMSMEDIA_BE_XINE:
02120 #ifdef __HAVE_XINE__
02121         return false;
02122 #endif
02123         break;
02124     default:
02125         // shouldn't be reached
02126         break;
02127     }
02128 
02129     throw MMSAVError(0, "MMSAV::sendAxisMotion() called but media backend does not match supported backends");
02130 
02131     return false;
02132 }
02133 
02134 bool MMSAV::sendEvent(MMSInputEvent *input) {
02135     // fire input events to the media backend
02136     switch (input->type) {
02137     case MMSINPUTEVENTTYPE_KEYPRESS:
02138         return sendKeyPress(input->key);
02139     case MMSINPUTEVENTTYPE_KEYRELEASE:
02140         return sendKeyRelease(input->key);
02141     case MMSINPUTEVENTTYPE_BUTTONPRESS:
02142         return sendButtonPress(input->posx, input->posy);
02143     case MMSINPUTEVENTTYPE_BUTTONRELEASE:
02144         return sendButtonRelease(input->posx, input->posy);
02145     case MMSINPUTEVENTTYPE_AXISMOTION:
02146         return sendAxisMotion(input->posx, input->posy);
02147     default:
02148         break;
02149     }
02150 
02151     return false;
02152 }
02153 
02154 /**
02155  * Returns true if stream contains a video stream.
02156  *
02157  * @return true if video stream
02158  */
02159 bool MMSAV::hasVideo() {
02160     switch(this->backend) {
02161         case MMSMEDIA_BE_GST:
02162 #ifdef __HAVE_GSTREAMER__
02163             return true;
02164 #endif
02165             break;
02166         case MMSMEDIA_BE_XINE:
02167 #ifdef __HAVE_XINE__
02168             return (xine_get_stream_info(this->stream, XINE_STREAM_INFO_HAS_VIDEO) == 1);
02169 #endif
02170             break;
02171         default:
02172             // shouldn't be reached
02173             break;
02174     }
02175 
02176     throw MMSAVError(0, "MMSAV::hasVideo() called but media backend does not match supported backends");
02177 }
02178 
02179 /**
02180  * Returns true if stream contains an audio stream.
02181  *
02182  * @return true if audio stream
02183  */
02184 bool MMSAV::hasAudio() {
02185     switch(this->backend) {
02186         case MMSMEDIA_BE_GST:
02187 #ifdef __HAVE_GSTREAMER__
02188             return false;
02189 #endif
02190             break;
02191         case MMSMEDIA_BE_XINE:
02192 #ifdef __HAVE_XINE__
02193             return (xine_get_stream_info(this->stream, XINE_STREAM_INFO_HAS_AUDIO) == 1);
02194 #endif
02195             break;
02196         default:
02197             // shouldn't be reached
02198             break;
02199     }
02200 
02201     throw MMSAVError(0, "MMSAV::hasAudio() called but media backend does not match supported backends");
02202 }

Generated by doxygen