/* This file is part of the KDE project
 *
 * Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef _KMPLAYERPROCESS_H_
#define _KMPLAYERPROCESS_H_

#include <tqobject.h>
#include <tqguardedptr.h>
#include <tqstring.h>
#include <tqcstring.h>
#include <tqstringlist.h>
#include <tqregexp.h>

#include <kurl.h>
#include <tdeio/global.h>

#include "kmplayerconfig.h"
#include "kmplayersource.h"

class TQWidget;
class TDEProcess;

namespace TDEIO {
    class Job;
    class TransferJob;
}

namespace KMPlayer {
    
class Settings;
class Viewer;
class Source;
class Callback;
class Backend_stub;

/*
 * Base class for all backend processes
 */
class KMPLAYER_EXPORT Process : public TQObject {
    Q_OBJECT
  
public:
    enum State {
        NotRunning = 0, Ready, Buffering, Playing
    };
    Process (TQObject * parent, Settings * settings, const char * n);
    virtual ~Process ();
    virtual void init ();
    virtual void initProcess (Viewer *);
    virtual TQString menuName () const;
    virtual void setAudioLang (int, const TQString &);
    virtual void setSubtitle (int, const TQString &);
    bool playing () const;
    KDE_NO_EXPORT TDEProcess * process () const { return m_process; }
    KDE_NO_EXPORT Source * source () const { return m_source; }
    virtual WId widget ();
    Viewer * viewer () const;
    void setSource (Source * src) { m_source = src; }
    virtual bool grabPicture (const KURL & url, int pos);
    bool supports (const char * source) const;
    State state () const { return m_state; }
    NodePtr mrl () const { return m_mrl; }
signals:
    void grabReady (const TQString & path);
public slots:
    virtual bool ready (Viewer *);
    bool play (Source *, NodePtr mrl);
    virtual bool stop ();
    virtual bool quit ();
    virtual bool pause ();
    /* seek (pos, abs) seek position in deci-seconds */
    virtual bool seek (int pos, bool absolute);
    /* volume from 0 to 100 */
    virtual bool volume (int pos, bool absolute);
    /* saturation/hue/contrast/brightness from -100 to 100 */
    virtual bool saturation (int pos, bool absolute);
    virtual bool hue (int pos, bool absolute);
    virtual bool contrast (int pos, bool absolute);
    virtual bool brightness (int pos, bool absolute);
protected slots:
    void rescheduledStateChanged ();
    void result (TDEIO::Job *);
protected:
    void setState (State newstate);
    virtual bool deMediafiedPlay ();
    virtual void terminateJobs ();
    Source * m_source;
    Settings * m_settings;
    NodePtrW m_mrl;
    State m_state;
    State m_old_state;
    TDEProcess * m_process;
    TDEIO::Job * m_job;
    TQString m_url;
    int m_request_seek;
    const char ** m_supported_sources;
private:
    TQGuardedPtr <Viewer> m_viewer;
};

/*
 * Base class for all MPlayer based processes
 */
class MPlayerBase : public Process {
    Q_OBJECT
  
public:
    MPlayerBase (TQObject * parent, Settings * settings, const char * n);
    ~MPlayerBase ();
    void initProcess (Viewer *);
public slots:
    virtual bool stop ();
    virtual bool quit ();
protected:
    bool sendCommand (const TQString &);
    TQStringList commands;
    bool m_use_slave : 1;
protected slots:
    virtual void processStopped (TDEProcess *);
private slots:
    void dataWritten (TDEProcess *);
};

class MPlayerPreferencesPage;
class MPlayerPreferencesFrame;

/*
 * MPlayer process
 */
class KDE_EXPORT MPlayer : public MPlayerBase {
    Q_OBJECT
  
public:
    MPlayer (TQObject * parent, Settings * settings);
    ~MPlayer ();
    virtual void init ();
    virtual TQString menuName () const;
    virtual WId widget ();
    virtual bool grabPicture (const KURL & url, int pos);
    virtual void setAudioLang (int, const TQString &);
    virtual void setSubtitle (int, const TQString &);
    bool run (const char * args, const char * pipe = 0L);
public slots:
    virtual bool deMediafiedPlay ();
    virtual bool stop ();
    virtual bool pause ();
    virtual bool seek (int pos, bool absolute);
    virtual bool volume (int pos, bool absolute);
    virtual bool saturation (int pos, bool absolute);
    virtual bool hue (int pos, bool absolute);
    virtual bool contrast (int pos, bool absolute);
    virtual bool brightness (int pos, bool absolute);
    MPlayerPreferencesPage * configPage () const { return m_configpage; }
    bool ready (Viewer *);
protected slots:
    void processStopped (TDEProcess *);
private slots:
    void processOutput (TDEProcess *, char *, int);
private:
    TQString m_process_output;
    TQString m_grabfile;
    TQWidget * m_widget;
    MPlayerPreferencesPage * m_configpage;
    TQString m_tmpURL;
    struct LangInfo {
        LangInfo (int i, const TQString & n) : id (i), name (n) {}
        int id; TQString name; SharedPtr <LangInfo> next;
    };
    SharedPtr <LangInfo> alanglist;
    WeakPtr <LangInfo> alanglist_end;
    SharedPtr <LangInfo> slanglist;
    WeakPtr <LangInfo> slanglist_end;
    int aid, sid;
    int old_volume;
    bool m_needs_restarted;
};

/*
 * MPlayer preferences page
 */
class KMPLAYER_NO_EXPORT MPlayerPreferencesPage : public PreferencesPage {
public:
    enum Pattern {
        pat_size = 0, pat_cache, pat_pos, pat_index,
        pat_refurl, pat_ref, pat_start,
        pat_dvdlang, pat_dvdsub, pat_dvdtitle, pat_dvdchapter,
        pat_vcdtrack, pat_cdromtracks,
        pat_last
    };
    MPlayerPreferencesPage (MPlayer *);
    KDE_NO_CDTOR_EXPORT ~MPlayerPreferencesPage () {}
    void write (TDEConfig *);
    void read (TDEConfig *);
    void sync (bool fromUI);
    void prefLocation (TQString & item, TQString & icon, TQString & tab);
    TQFrame * prefPage (TQWidget * parent);
    TQRegExp m_patterns[pat_last];
    int cachesize;
    TQString mplayer_path;
    TQString additionalarguments;
    bool alwaysbuildindex;
private:
    MPlayer * m_process;
    MPlayerPreferencesFrame * m_configframe;
};

/*
 * Base class for all recorders
 */
class KMPLAYER_EXPORT Recorder {
public:
    KDE_NO_EXPORT const KURL & recordURL () const { return m_recordurl; }
    KDE_NO_EXPORT void setURL (const KURL & url) { m_recordurl = url; }
protected:
    KURL m_recordurl;
};

/*
 * MEncoder recorder
 */
class MEncoder : public MPlayerBase, public Recorder {
    Q_OBJECT
  
public:
    MEncoder (TQObject * parent, Settings * settings);
    ~MEncoder ();
    virtual void init ();
    virtual bool deMediafiedPlay ();
public slots:
    virtual bool stop ();
};

/*
 * MPlayer recorder, runs 'mplayer -dumpstream'
 */
class KMPLAYER_NO_EXPORT MPlayerDumpstream
  : public MPlayerBase, public Recorder {
    Q_OBJECT
  
public:
    MPlayerDumpstream (TQObject * parent, Settings * settings);
    ~MPlayerDumpstream ();
    virtual void init ();
    virtual bool deMediafiedPlay ();
public slots:
    virtual bool stop ();
};

class XMLPreferencesPage;
class XMLPreferencesFrame;

/*
 * Base class for all backend processes having the KMPlayer::Backend interface
 */
class KMPLAYER_EXPORT CallbackProcess : public Process {
    Q_OBJECT
  
    friend class Callback;
public:
    CallbackProcess (TQObject * parent, Settings * settings, const char * n, const TQString & menu);
    ~CallbackProcess ();
    virtual void setStatusMessage (const TQString & msg);
    virtual void setErrorMessage (int code, const TQString & msg);
    virtual void setFinished ();
    virtual void setPlaying ();
    virtual void setStarted (TQCString dcopname, TQByteArray & data);
    virtual void setMovieParams (int length, int width, int height, float aspect, const TQStringList & alang, const TQStringList & slang);
    virtual void setMoviePosition (int position);
    virtual void setLoadingProgress (int percentage);
    virtual void setAudioLang (int, const TQString &);
    virtual void setSubtitle (int, const TQString &);
    virtual TQString menuName () const;
    virtual WId widget ();
    KDE_NO_EXPORT TQByteArray & configData () { return m_configdata; }
    KDE_NO_EXPORT bool haveConfig () { return m_have_config == config_yes; }
    bool getConfigData ();
    void setChangedData (const TQByteArray &);
    TQString dcopName ();
    NodePtr configDocument () { return configdoc; }
    void initProcess (Viewer *);
    virtual bool deMediafiedPlay ();
public slots:
    bool stop ();
    bool quit ();
    bool pause ();
    bool seek (int pos, bool absolute);
    bool volume (int pos, bool absolute);
    bool saturation (int pos, bool absolute);
    bool hue (int pos, bool absolute);
    bool contrast (int pos, bool absolute);
    bool brightness (int pos, bool absolute);
signals:
    void configReceived ();
protected slots:
    void processStopped (TDEProcess *);
    void processOutput (TDEProcess *, char *, int);
protected:
    Callback * m_callback;
    Backend_stub * m_backend;
    TQString m_menuname;
    TQByteArray m_configdata;
    TQByteArray m_changeddata;
    XMLPreferencesPage * m_configpage;
    NodePtr configdoc;
    bool in_gui_update;
    enum { config_unknown, config_probe, config_yes, config_no } m_have_config;
    enum { send_no, send_try, send_new } m_send_config;
};

/*
 * Config document as used by kxineplayer backend
 */
struct KMPLAYER_NO_EXPORT ConfigDocument : public Document {
    ConfigDocument ();
    ~ConfigDocument ();
    NodePtr childFromTag (const TQString & tag);
};

/*
 * Element for ConfigDocument
 */
struct KMPLAYER_NO_EXPORT ConfigNode : public DarkNode {
    ConfigNode (NodePtr & d, const TQString & tag);
    KDE_NO_CDTOR_EXPORT ~ConfigNode () {}
    NodePtr childFromTag (const TQString & tag);
    TQWidget * w;
};

/*
 * Element for ConfigDocument, defining type of config item
 */
struct KMPLAYER_NO_EXPORT TypeNode : public ConfigNode {
    TypeNode (NodePtr & d, const TQString & t);
    KDE_NO_CDTOR_EXPORT ~TypeNode () {}
    NodePtr childFromTag (const TQString & tag);
    void changedXML (TQTextStream & out);
    TQWidget * createWidget (TQWidget * parent);
    const char * nodeName () const { return tag.ascii (); }
    TQString tag;
};

/*
 * Preference page for XML type of docuement
 */
class KMPLAYER_NO_EXPORT XMLPreferencesPage : public PreferencesPage {
public:
    XMLPreferencesPage (CallbackProcess *);
    ~XMLPreferencesPage ();
    void write (TDEConfig *);
    void read (TDEConfig *);
    void sync (bool fromUI);
    void prefLocation (TQString & item, TQString & icon, TQString & tab);
    TQFrame * prefPage (TQWidget * parent);
private:
    CallbackProcess * m_process;
    XMLPreferencesFrame * m_configframe;
};

/*
 * Xine backend process
 */
class KMPLAYER_NO_EXPORT Xine : public CallbackProcess, public Recorder {
    Q_OBJECT
  
public:
    Xine (TQObject * parent, Settings * settings);
    ~Xine ();
public slots:
    bool ready (Viewer *);
};

/*
 * GStreamer backend process
 */
class KMPLAYER_NO_EXPORT GStreamer : public CallbackProcess {
    Q_OBJECT
  
public:
    GStreamer (TQObject * parent, Settings * settings);
    ~GStreamer ();
public slots:
    virtual bool ready (Viewer *);
};

/*
 * ffmpeg backend recorder
 */
class KMPLAYER_EXPORT FFMpeg : public Process, public Recorder {
    Q_OBJECT
  
public:
    FFMpeg (TQObject * parent, Settings * settings);
    ~FFMpeg ();
    virtual void init ();
    virtual bool deMediafiedPlay ();
public slots:
    virtual bool stop ();
    virtual bool quit ();
private slots:
    void processStopped (TDEProcess *);
};

/*
 * npplayer backend
 */

class KMPLAYER_NO_EXPORT NpStream : public TQObject {
    Q_OBJECT
  
public:
    enum Reason {
        NoReason = -1,
        BecauseDone = 0, BecauseError = 1, BecauseStopped = 2
    };

    NpStream (TQObject *parent, TQ_UINT32 stream_id, const KURL & url);
    ~NpStream ();

    void open ();
    void close ();

    KURL url;
    TQByteArray pending_buf;
    TDEIO::TransferJob *job;
    timeval data_arrival;
    TQ_UINT32 bytes;
    TQ_UINT32 stream_id;
    TQ_UINT32 content_length;
    Reason finish_reason;
    TQString mimetype;
signals:
    void stateChanged ();
    void redirected (TQ_UINT32, const KURL &);
private slots:
    void slotResult (TDEIO::Job*);
    void slotData (TDEIO::Job*, const TQByteArray& qb);
    void redirection (TDEIO::Job *, const KURL &url);
    void slotMimetype (TDEIO::Job *, const TQString &mime);
    void slotTotalSize (TDEIO::Job *, TDEIO::filesize_t sz);
};

class KMPLAYER_NO_EXPORT NpPlayer : public Process {
    Q_OBJECT
  
public:
    NpPlayer (TQObject * parent, Settings * settings, const TQString & srv);
    ~NpPlayer ();
    virtual void init ();
    virtual bool deMediafiedPlay ();
    virtual void initProcess (Viewer * viewer);
    virtual TQString menuName () const;

    void setStarted (const TQString & srv);
    void requestStream (const TQString & path, const TQString & url, const TQString & target);
    void destroyStream (const TQString & path);

    KDE_NO_EXPORT const TQString & destination () const { return service; }
    KDE_NO_EXPORT const TQString & interface () const { return iface; }
    KDE_NO_EXPORT TQString objectPath () const { return path; }
    TQString evaluateScript (const TQString & scr);
signals:
    void evaluate (const TQString & scr, TQString & result);
    void openUrl (const KURL & url, const TQString & target);
public slots:
    virtual bool stop ();
    virtual bool quit ();
public slots:
    bool ready (Viewer *);
private slots:
    void processOutput (TDEProcess *, char *, int);
    void processStopped (TDEProcess *);
    void wroteStdin (TDEProcess *);
    void streamStateChanged ();
    void streamRedirected (TQ_UINT32, const KURL &);
protected:
    virtual void terminateJobs ();
private:
    void sendFinish (TQ_UINT32 sid, TQ_UINT32 total, NpStream::Reason because);
    void processStreams ();
    TQString service;
    TQString iface;
    TQString path;
    TQString filter;
    TQString m_base_url;
    typedef TQMap <TQ_UINT32, NpStream *> StreamMap;
    StreamMap streams;
    TQString remote_service;
    TQByteArray send_buf;
    bool write_in_progress;
};

} // namespace

#endif //_KMPLAYERPROCESS_H_