/***************************************************************************
 *   Copyright (C) 2005 by Reel Multimedia                                 *
 *                                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// XineLib.h
 
#ifndef XINE_MEDIAPLAYER_XINE_LIB_H_INCLUDED
#define XINE_MEDIAPLAYER_XINE_LIB_H_INCLUDED

#include <string>
#include <vdr/keys.h>

#include "Reel.h"
#include "XineEvent.h"
#include "VdrXineMpIf.h"



// xine struct declarations.
typedef struct xine_s             xine_t;
typedef struct xine_stream_s      xine_stream_t;
typedef struct xine_audio_port_s  xine_audio_port_t;
typedef struct xine_event_queue_s xine_event_queue_t;
typedef struct xine_video_port_s  xine_video_port_t;
//static _stream_infos_t

typedef struct  myxine_mrl_s
{
    char      *origin; /* file plugin: path */
    char      *mrl;    /* <type>://<location> */
    char      *link;
    uint32_t   type;   /* see below */
    off_t      size;   /* size of this source, may be 0 */
}
myxine_mrl_t;


namespace Reel
{
namespace XineMediaplayer
{
    extern VdrXineMpIf *vxi;
    extern int useOld;
    class Player;

    class XineLib /* final, singleton */
     {
    public:
        static XineLib &Instance() NO_THROW;
            // Return singleton instance.

        void Exit() NO_THROW;
            // Free all resources.

        //bool GetEvent(std::auto_ptr<XineEventBase> &cpEvent) const THROWS;
        XineEventBase *GetEvent() const THROWS; 
            // Return a xine event.

        void Init() THROWS;
            // Initialize xine-lib and the xine stream.
            // Throws XineError, in this case the XineLib will be in the disposed state.

        void SetXineConfig() THROWS; 

        /*
        void SetAudioLang() THROWS; 

        void SetSpuLang() THROWS;
        */

        void Open(char const *mrl) THROWS;
            // Open a stream.
            // Throws XineError, in this case the stream will be in the closed state.

        void Close() NO_THROW;
            // Close the stream.

        void Play(int startPos, int startTime) THROWS;
            // Play the stream from a given position.
            // Throws XineError, in this case the stream will be in the stopped state.

        void ProcessKeyMenuMode(eKeys key) THROWS;
            // Process a key in menu domain

        void ProcessKey(eKeys key,bool isMusic) THROWS;
            // Process a key.

        void Stop() NO_THROW;
            // Stop stream playback.

        std::string XineGetErrorStr() const NO_THROW;
            // Return last error of the xine stream as a string.

        bool GetReplayMode(bool &Play, bool &Forward, int &Speed);

        const char *GetTitleString();
        const char *GetAspectString();

        bool GetAudioLangCode(char *lang, int track = -1);

        bool GetSpuLangCode(char *lang, int track = -1);
        /// default value -1 means current track

        void SetAudioTrack(int track);
        void SetSpuTrack(int track);

        // ---- pos/length info 
        bool GetIndex(int &current, int &total);
            //  writes current and total time of stream 
            //  total will be 0 if xine_get_pos_length fails 
        xine_stream_t *GetStream(); 
        const char *GetSetupLang() const;
        void PrintXineConfig();
        void PrintXinePlugins();
        void ResetStream();

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // xine stream_info
        uint32_t GetBitrate();
        
        uint32_t Bitrate();

        uint32_t Seekable();

        uint32_t VideoWidth();

        uint32_t VideoHeight();

        uint32_t VideoRatio();

        uint32_t VideoChannels();

        uint32_t VideoStreams();

        uint32_t VideoBitrate();

        uint32_t VideoFourcc();

        uint32_t VideoHandled();

        uint32_t FrameDuration();

        uint32_t AudioChannels();

        uint32_t AudioBits();

        uint32_t AudioSamplerate();

        uint32_t AudioBitrate();

        uint32_t AudioFourcc();

        uint32_t AudioHandled();

        uint32_t HasChapters();

        uint32_t HasVideo();

        uint32_t HasAudio();

        uint32_t IgnoreVideo();

        uint32_t IgnoreAudio();

        uint32_t IgnoreSpu();

        uint32_t VideoHasStill();

        uint32_t MaxAudioChannel();

        uint32_t MaxSpuChannel();

        uint32_t AudioMode();

        uint32_t SkippedFrames();

        uint32_t DiscardedFrames();

        uint32_t VideoAfd();

        uint32_t DvdTitleNumber();

        uint32_t DvdTitleCount();

        uint32_t DvdChapterNumber();

        uint32_t DvdChapterCount();

        uint32_t DvdAngleNumber();

        uint32_t DvdAngleCount();

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // xine meta infos 
        const char *GetTitle() const;
       
        const char *Comment() const;

        const char *Artist() const;

        const char *Genre() const;

        const char *Album() const;

        const char *Year() const;

        const char *VideoCodec() const;

        const char *AudioCodec() const;

        const char *SystemLayer() const;

        const char *InputPlugin() const;

        const char *CDIndexDiscId() const;

        const char *TrackNumber() const;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // xine get stream parameter 

        int GetParamSpeed();

        int GetParamAVOffset();

        int GetParamAudioChannelLogical();

        int GetParamSPUChannel();

        int GetParamParamVideoChannel();

        int GetParamAudioVolume();

        int GetParamAudioMute();

        int GetParamAudioComprLevel();

        int GetParamAudioAmpLevel();

        int GetParamAudioReportLevel();

        int GetParamVerbosity();

        int GetParamSpuOffset();

        int GetParamIgnoreVideo();

        int GetParamIgnoreAudio();

        int GetParamIgnoreSpu();

        int GetParamBroadcasterPort();

        int GetParamMetronomPrebuffer();

        int GetParamAudioAmpMute();

        int GetParamFineSpeed();

        int GetParamEarlyFinishedEvent();

        int GetParamGaplessSwitch();

        int GetParamDelayFinishedEvent();

        int GetParamDeinterlace();

        int GetParamVoAspectRatio();

        int GetParamVoHue();

        int GetParamVoSaturation();

        int GetParamVoContrast();

        int GetParamVoBrightness();

        int GetParamVoZoomX();

        int GetParamVoZommY();

        int GetParamPanScan();
        
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // xine set stream parameter 

        void SetParamSpeed(int val);

        void SetParamAVOffset(int val);

        void SetParamAudioChannelLogical(int val);

        void SetParamSPUChannel(int val);

        void SetParamParamVideoChannel(int val);

        void SetParamAudioVolume(int val);

        void SetParamAudioMute(int val);

        void SetParamAudioComprLevel(int val);

        void SetParamAudioAmpLevel(int val);

        void SetParamAudioReportLevel(int val);

        void SetParamVerbosity(int val);

        void SetParamSpuOffset(int val);

        void SetParamIgnoreVideo(int val);

        void SetParamIgnoreAudio(int val);

        void SetParamIgnoreSpu(int val);

        void SetParamBroadcasterPort(int val);

        void SetParamMetronomPrebuffer(int val);

        void SetParamAudioAmpMute(int val);

        void SetParamFineSpeed(int val);

        void SetParamEarlyFinishedEvent(int val);

        void SetParamGaplessSwitch(int val);

        //void SetParamDelayFinishedEvent(int val);

        myxine_mrl_t **GetMrls(const char *start_mrl, int *num_mrls);

    private:
        static XineLib           instance_;

        XineLib() NO_THROW;
        ~XineLib() NO_THROW;

        XineLib(XineLib const &); // No copying.
        XineLib &operator=(XineLib const &); // No assigning.

        void ProcessInputKeyMenuMode(eKeys key) THROWS;
            // PRE: Stream exists.
        void ProcessInputKey(eKeys key) THROWS;
            // PRE: Stream exists.
        void ProcessPlaymodeKey(eKeys key,bool isMusic) THROWS;
            // PRE: Stream exists.
        void ProcessSeekKey(eKeys key) THROWS;
            // PRE: Stream exists.

        xine_t             *xine_;
        xine_audio_port_t  *aoPort_;
        xine_video_port_t  *voPort_;
        xine_stream_t      *stream_;
        xine_event_queue_t *eventQueue_;
		bool                streamOpen_, streamPlaying_;
    };

    class XineError /* final */
    {
    public:
        XineError(char const *msg) NO_THROW;

        // default copying, assignment and destruction do ok.

        char const *Msg() const NO_THROW;

    private:
        std::string msg_;
    };

    void LogXineError(XineError const &ex) NO_THROW;

    inline XineLib &XineLib::Instance() NO_THROW
    {
        return instance_;
    }

    inline XineLib::~XineLib() NO_THROW
    {
        Exit();
    }

    inline bool XineLib::GetReplayMode(bool &Play, bool &Forward, int &Speed)
    {
        Play = true;
        Forward = false;
        Speed = -1;
        return true;
    }    

    inline bool XineLib::GetIndex(int &current, int &total)
    {
      if (!stream_)
      {
         return false;
      }
       /*
              int *pos_stream,  * 0..65535     *
              int *pos_time,    * milliseconds *
              int *length_time) * milliseconds *
      */
      
      int pal_ms2fps = 40; 
      //int ntfs_ms2fps = 29.97; 
      int pos;
      int pos_time;
      int length_time;

      int ret = xine_get_pos_length (stream_, &pos, &pos_time ,&length_time);

      current = (int)pos_time/pal_ms2fps;
      total = (int)length_time/pal_ms2fps;

      return ret;
    }

    inline xine_stream_t *XineLib::GetStream() 
    {
        return stream_;
    }
   
    inline const char *XineLib::GetAspectString()
    {
       // TODO XINE_STREAM_INFO_VIDEO_AFD
       int ret = VideoAfd();
       switch (ret)
       {
           case XINE_VIDEO_AFD_NOT_PRESENT:
               return "na";
           case XINE_VIDEO_AFD_RESERVED_0:
           case XINE_VIDEO_AFD_RESERVED_1:
               //printf(" Debug XineLib -----------------------------  XINE_VIDEO_AFD_RESERVED %d  ?? --------------- \n", ret);
               return "reserved";
           case XINE_VIDEO_AFD_BOX_14_9_TOP:
               //printf(" Debug XineLib -----------------------------  XINE_VIDEO_AFD_BOX_14_9_TOP ?? --------------- \n");
           case XINE_VIDEO_AFD_BOX_16_9_TOP:
           case XINE_VIDEO_AFD_BOX_GT_16_9_CENTRE:
               return "16:9";
           case XINE_VIDEO_AFD_RESERVED_5:
           case XINE_VIDEO_AFD_RESERVED_6:
           case XINE_VIDEO_AFD_RESERVED_7:
               //printf(" Debug XineLib -----------------------------  XINE_VIDEO_AFD_RESERVED %d  ?? --------------- \n", ret);
               return "reserved";
           case XINE_VIDEO_AFD_SAME_AS_FRAME:
               printf(" Debug XineLib -----------------------------  XINE_VIDEO_AFD_SAME_AS_FRAME?? --------------- \n");
               return "saf";
           case XINE_VIDEO_AFD_4_3_CENTRE:
               return "4:3";
           case XINE_VIDEO_AFD_16_9_CENTRE:
           case XINE_VIDEO_AFD_14_9_CENTRE:
               return "16:9";
           case XINE_VIDEO_AFD_RESERVED_12:
               //printf(" Debug XineLib -----------------------------  XINE_VIDEO_AFD_RESERVED %d  ?? --------------- \n", ret);
               return "reserved";
           case XINE_VIDEO_AFD_4_3_PROTECT_14_9:
           case XINE_VIDEO_AFD_16_9_PROTECT_14_9:
           case XINE_VIDEO_AFD_16_9_PROTECT_4_3:
               //printf(" Debug XineLib -----------------------------  XINE_VIDEO_AFD_?? _PROTECT_ ?? %d --------------- \n", ret);
               return "16:9";
       }
      printf(" Debug XineLib ------------------ No valid aspect ----------------- \n");
       return "??";
    }

    inline bool XineLib::GetAudioLangCode(char *langbuf, int track)
    {
       strcpy (langbuf, "");
       if(!stream_) return false;
       if (xine_get_audio_lang(stream_, track, langbuf)== 0)
       {
            printf ( " GetAudioLangCode  NO Info  return false\n");
            return false;
       }
       return true;
    }

    inline void XineLib::SetAudioTrack(int track)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, track);
    }

    inline bool XineLib::GetSpuLangCode(char *langbuf, int track) 
    {
       strcpy (langbuf, "");
       if(!stream_) return false;
       if (xine_get_spu_lang(stream_, track, langbuf) == 0)
       {
            printf ( " GetSpuLangCode %s    return true\n", langbuf);
            return false;
       }
       return true;
    }

    inline void XineLib::SetSpuTrack(int track)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_SPU_CHANNEL, track);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // xine stream info
    inline uint32_t XineLib::GetBitrate()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_,XINE_STREAM_INFO_BITRATE);
    }

    inline uint32_t XineLib::Seekable()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_SEEKABLE);
    }

    inline uint32_t XineLib::VideoWidth()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_WIDTH);
    }

    inline uint32_t XineLib::VideoHeight()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_HEIGHT);
    }

    inline uint32_t XineLib::VideoRatio()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_RATIO);
    }

    inline uint32_t XineLib::VideoChannels()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_CHANNELS);
    }

    inline uint32_t XineLib::VideoStreams()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_STREAMS);
    }

    inline uint32_t XineLib::VideoBitrate()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_BITRATE);
    }

    inline uint32_t XineLib::VideoFourcc()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_FOURCC);
    }

    inline uint32_t XineLib::VideoHandled()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_HANDLED);
    }

    inline uint32_t XineLib::FrameDuration()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_FRAME_DURATION);
    }

    inline uint32_t XineLib::AudioChannels()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_CHANNELS);
    }

    inline uint32_t XineLib::AudioBits()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_BITS);
    }

    inline uint32_t XineLib::AudioSamplerate()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_SAMPLERATE);
    }

    inline uint32_t XineLib::AudioBitrate()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_BITRATE);
    }

    inline uint32_t XineLib::AudioFourcc()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_FOURCC);
    }
    inline uint32_t XineLib::AudioHandled()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_HANDLED);
    }

    inline uint32_t XineLib::HasChapters()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_HAS_CHAPTERS);
    }

    inline uint32_t XineLib::HasVideo()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_HAS_VIDEO);
    }

    inline uint32_t XineLib::HasAudio()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_HAS_AUDIO);
    }

    inline uint32_t XineLib::IgnoreVideo()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_IGNORE_VIDEO);
    }

    inline uint32_t XineLib::IgnoreAudio()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_IGNORE_AUDIO);
    }
    inline uint32_t XineLib::IgnoreSpu()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_IGNORE_SPU);
    }

    inline uint32_t XineLib::VideoHasStill()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_HAS_STILL);
    }

    inline uint32_t XineLib::MaxAudioChannel()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
    }

    inline uint32_t XineLib::MaxSpuChannel()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
    }

    inline uint32_t XineLib::AudioMode()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_AUDIO_MODE);
    }

    inline uint32_t XineLib::SkippedFrames()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_SKIPPED_FRAMES);
    }

    inline uint32_t XineLib::DiscardedFrames()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_DISCARDED_FRAMES);
    }

    inline uint32_t XineLib::VideoAfd()
    {
        if(!stream_) return XINE_VIDEO_AFD_NOT_PRESENT;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_VIDEO_AFD);
    }

    inline uint32_t XineLib::DvdTitleNumber()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_DVD_TITLE_NUMBER);
    }

    inline uint32_t XineLib::DvdTitleCount()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_DVD_TITLE_COUNT);
    }

    inline uint32_t XineLib::DvdChapterNumber()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER);
    }

    inline uint32_t XineLib::DvdChapterCount()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_DVD_CHAPTER_COUNT);
    }

    inline uint32_t XineLib::DvdAngleNumber()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_DVD_ANGLE_NUMBER);
    }

    inline uint32_t XineLib::DvdAngleCount()
    {
        if(!stream_) return 0;
        return  xine_get_stream_info(stream_, XINE_STREAM_INFO_DVD_ANGLE_COUNT);
    }




    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // xine meta infos 
    inline const char *XineLib::GetTitle() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_TITLE);
    }

    inline const char *XineLib::Comment() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_COMMENT);
    }

    inline const char *XineLib::Artist() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_ARTIST);
    }

    inline const char *XineLib::Genre() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_GENRE);
    }

    inline const char *XineLib::Album() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_ALBUM);
    }

    inline const char *XineLib::Year() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_YEAR);
    }

    inline const char *XineLib::VideoCodec() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_VIDEOCODEC);
    }

    inline const char *XineLib::AudioCodec() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_AUDIOCODEC);
    }

    inline const char *XineLib::SystemLayer() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_SYSTEMLAYER);
    }

    inline const char *XineLib::InputPlugin() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_INPUT_PLUGIN);
    }

    inline const char *XineLib::CDIndexDiscId() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_CDINDEX_DISCID);
    }

    inline const char *XineLib::TrackNumber() const
    {
        if(!stream_) return NULL;
        return  xine_get_meta_info(stream_, XINE_META_INFO_TRACK_NUMBER);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // xine stream parameter 
    inline int XineLib::GetParamSpeed()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_,XINE_PARAM_SPEED);
    }

    inline int XineLib::GetParamAVOffset()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AV_OFFSET);
    }

    inline int XineLib::GetParamAudioChannelLogical()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
    }

    inline int XineLib::GetParamSPUChannel()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_SPU_CHANNEL);
    }

    inline int XineLib::GetParamParamVideoChannel()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VIDEO_CHANNEL);
    }

    inline int XineLib::GetParamAudioVolume()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AUDIO_VOLUME);
    }

    inline int XineLib::GetParamAudioMute()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AUDIO_MUTE);
    }

    inline int XineLib::GetParamAudioComprLevel()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AUDIO_COMPR_LEVEL);
    }

    inline int XineLib::GetParamAudioAmpLevel()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL);
    }

    inline int XineLib::GetParamAudioReportLevel()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AUDIO_REPORT_LEVEL);
    }

    inline int XineLib::GetParamVerbosity()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VERBOSITY);
    }

    inline int XineLib::GetParamSpuOffset()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_SPU_OFFSET);
    }

    inline int XineLib::GetParamIgnoreVideo()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_IGNORE_VIDEO);
    }

    inline int XineLib::GetParamIgnoreAudio()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_IGNORE_AUDIO);
    }

    inline int XineLib::GetParamIgnoreSpu()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_IGNORE_SPU);
    }

    inline int XineLib::GetParamBroadcasterPort()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_BROADCASTER_PORT);
    }

    inline int XineLib::GetParamMetronomPrebuffer()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_METRONOM_PREBUFFER);
    }

    inline int XineLib::GetParamAudioAmpMute()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_AUDIO_AMP_MUTE);
    }

    inline int XineLib::GetParamFineSpeed()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_FINE_SPEED);
    }

    inline int XineLib::GetParamEarlyFinishedEvent()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_EARLY_FINISHED_EVENT);
    }

    inline int XineLib::GetParamGaplessSwitch()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_GAPLESS_SWITCH);
    }

    /*
    inline int XineLib::GetParamDelayFinishedEvent()
    {
       return xine_get_param(stream_, XINE_PARAM_DELAY_FINISHED_EVENT);
    } */

    //// 
    inline int XineLib::GetParamDeinterlace()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_DEINTERLACE);
    }

    inline int XineLib::GetParamVoAspectRatio()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_ASPECT_RATIO);
    }

    inline int XineLib::GetParamVoHue()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_HUE);
    }

    inline int XineLib::GetParamVoSaturation()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_SATURATION);
    }

    inline int XineLib::GetParamVoContrast()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_CONTRAST);
    }

    inline int XineLib::GetParamVoBrightness()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_BRIGHTNESS);
    }

    inline int XineLib::GetParamVoZoomX()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_ZOOM_X);
    }

    inline int XineLib::GetParamVoZommY()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_ZOOM_Y);
    }

    inline int XineLib::GetParamPanScan()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_PAN_SCAN);
    }

    /*    inline int XineLib::GetParamTV()
    {
       return xine_get_param(stream_, XINE_PARAM_VO_TVMODE);
    }

    inline int XineLib::GetParamWindowWidth()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_WINDOW_WIDTH);
    }

    inline int XineLib::GetParamDelayFinishedEvent()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_WINDOW_HEIGHT);
    }

    inline int XineLib::GetParamDelayFinishedEvent()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_CROP_LEFT);
    }

    inline int XineLib::GetParamDelayFinishedEvent()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_CROP_RIGHT);
    }

    inline int XineLib::GetParamDelayFinishedEvent()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_CROP_TOP);
    }

    inline int XineLib::GetParamDelayFinishedEvent()
    {
       if(!stream_) return 0;
       return xine_get_param(stream_, XINE_PARAM_VO_CROP_BOTTOM);
    }
    */

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // xine stream parameter 

    inline void XineLib::SetParamSpeed(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_,XINE_PARAM_SPEED, val);
    }

    inline void XineLib::SetParamAVOffset(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AV_OFFSET, val);
    }

    inline void XineLib::SetParamAudioChannelLogical(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, val);
    }

    inline void XineLib::SetParamSPUChannel(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_SPU_CHANNEL, val);
    }

    inline void XineLib::SetParamParamVideoChannel(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_VIDEO_CHANNEL, val);
    }

    inline void XineLib::SetParamAudioVolume(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_VOLUME, val);
    }

    inline void XineLib::SetParamAudioMute(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_MUTE, val);
    }

    inline void XineLib::SetParamAudioComprLevel(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_COMPR_LEVEL, val);
    }

    inline void XineLib::SetParamAudioAmpLevel(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, val);
    }

    inline void XineLib::SetParamAudioReportLevel(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_REPORT_LEVEL, val);
    }

    inline void XineLib::SetParamVerbosity(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_VERBOSITY, val);
    }

    inline void XineLib::SetParamSpuOffset(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_SPU_OFFSET, val);
    }

    inline void XineLib::SetParamIgnoreVideo(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_IGNORE_VIDEO, val);
    }

    inline void XineLib::SetParamIgnoreAudio(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_IGNORE_AUDIO, val);
    }

    inline void XineLib::SetParamIgnoreSpu(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_IGNORE_SPU, val);
    }

    inline void XineLib::SetParamBroadcasterPort(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_BROADCASTER_PORT, val);
    }

    inline void XineLib::SetParamMetronomPrebuffer(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_METRONOM_PREBUFFER, val);
    }

    inline void XineLib::SetParamAudioAmpMute(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_MUTE, val);
    }

    inline void XineLib::SetParamFineSpeed(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_FINE_SPEED, val);
    }

    inline void XineLib::SetParamEarlyFinishedEvent(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_EARLY_FINISHED_EVENT, val);
    }

    inline void XineLib::SetParamGaplessSwitch(int val)
    {
       if(!stream_) return;
       xine_set_param(stream_, XINE_PARAM_GAPLESS_SWITCH, val);
    }

    /*
    inline void XineLib::SetParamDelayFinishedEvent(int val)
    {
       xine_set_param(stream_, XINE_PARAM_DELAY_FINISHED_EVENT, val);
    }
    */

    inline myxine_mrl_t **XineLib::GetMrls(const char *start_mrl, int *num_mrls)
    {
        const char *id = InputPlugin();
        if(!xine_ || !id) return NULL;
        return reinterpret_cast<myxine_mrl_t **>(xine_get_browse_mrls (xine_, id, start_mrl, num_mrls));
    }
}
}

#endif // XINE_MEDIAPLAYER_XINE_LIB_H_INCLUDED
