// (C) 2005 Max Howell (max.howell@methylblue.com)
// See COPYING file for licensing information

#ifndef CODEINE_VIDEOWINDOW_H
#define CODEINE_VIDEOWINDOW_H

#include "../codeine.h"
#include <tqtimer.h>
#include <tqwidget.h>
#include <kurl.h>
#include <stdint.h>
#include <vector>
#include <xine.h>


typedef struct xine_s xine_t;
typedef struct xine_stream_s xine_stream_t;
typedef struct xine_video_port_s xine_video_port_t;
typedef struct xine_audio_port_s xine_audio_port_t;
typedef struct xine_event_queue_s xine_event_queue_t;
typedef struct xine_post_s xine_post_t;
typedef struct xine_osd_s xine_osd_t;

namespace Engine {
   typedef std::vector<int16_t> Scope;
}


namespace Codeine
{
   /** Functions declared here are defined in:
    *    xineEngine.cpp
    *    videoWindow.cpp
    */
   class VideoWindow : public TQWidget
   {
   TQ_OBJECT

      enum PosTimeLength { Pos, Time, Length };

      static VideoWindow *s_instance;
      static bool s_logarithmicVolume;

      VideoWindow( const VideoWindow& ); //disable
      VideoWindow &operator=( const VideoWindow& ); //disable

      friend class TheStream;
      friend VideoWindow* const engine();
      friend VideoWindow* const videoWindow();

   public:
      VideoWindow( TQWidget *parent );
     ~VideoWindow();

      bool init();
      void exit();

      bool load( const KURL &url );
      bool play( uint = 0 );

      uint position() const { return posTimeLength( Pos ); }
      uint time() const { return posTimeLength( Time ); }
      uint length() const { return posTimeLength( Length ); }

      bool isMuted() const;
      uint volume() const;

      const Engine::Scope &scope();
      Engine::State state() const;

      operator xine_t*() const { return m_xine; }
      operator xine_stream_t*() const { return m_stream; }

   public slots:
      void pause();
      void record();
      void seek( uint );
      void stop();

      ///special slot, see implementation to facilitate understanding
      void setStreamParameter( int );
      void setMuted(bool);

   signals:
      void stateChanged( Engine::State );
      void statusMessage( const TQString& );
      void titleChanged( const TQString& );
      void audioChannelsChanged( const TQStringList &);
      void subtitleChannelsChanged( const TQStringList &);

   private:
      static void xineEventListener( void*, const xine_event_t* );

      uint posTimeLength( PosTimeLength ) const;
      void showErrorMessage();

      virtual void customEvent( TQCustomEvent* );
      virtual void timerEvent( TQTimerEvent* );

      void eject();

      void announceStateChange() { emit stateChanged( state() ); }

      xine_osd_t         *m_osd;
      xine_stream_t      *m_stream;
      xine_event_queue_t *m_eventQueue;
      xine_video_port_t  *m_videoPort;
      xine_audio_port_t  *m_audioPort;
      xine_post_t        *m_post;
      xine_t             *m_xine;

      Engine::Scope m_scope;
      int64_t m_current_vpts;

      KURL m_url;

   public:
      TQString fileFilter() const;

   public slots:
      void toggleDVDMenu();
      void showOSD( const TQString& );

   /// Stuff to do with video and the video window/widget
   private:
      static void destSizeCallBack( void*, int, int, double, int*, int*, double* );
      static void frameOutputCallBack( void*, int, int, double, int*, int*, int*, int*, double*, int*, int* );
      static int makeVolumeLogarithmic(int volume);

      void initVideo();
      void cleanUpVideo();

   public:
      static const uint CURSOR_HIDE_TIMEOUT = 2000;

      virtual TQSize sizeHint() const;
      virtual TQSize minimumSizeHint() const;

      void *x11Visual() const;
      void becomePreferredSize();
      TQImage captureFrame() const;

   public slots:
      void resetZoom();

   private slots:
      void hideCursor();

   private:
      virtual void contextMenuEvent( TQContextMenuEvent* );
      virtual bool event( TQEvent* );
      virtual bool x11Event( XEvent* );

      double m_displayRatio;
      TQTimer m_timer;
   };

   //global function for general use by Codeine
   //videoWindow() is const for Xlib-thread-safety reasons
   inline VideoWindow* const videoWindow() { return VideoWindow::s_instance; }
   inline VideoWindow* const engine() { return VideoWindow::s_instance; }
}

#endif
