/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */


/*
 * scale and output functions are taken from minimad.c example of libmad package that is
 * copyrighted 2000-2001 by Robert Leslie
 */


#ifndef NMM_MPEGAUDIODECODENODE_HPP
#define NMM_MPEGAUDIODECODENODE_HPP NMM_MPEGAUDIODECODENODE_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/multimedia/GenericProcessorNode.hpp"
#include "nmm/multimedia/ISyncResetImpl.hpp"
#include "nmm/multimedia/interfaces/ITrackImpl.hpp"
//#include "nmm/plugins/interfaces/ISeekReceiverImpl.hpp"
#include "nmm/multimedia/interfaces/ITrackDurationImpl.hpp"
#include "nmm/plugins/interfaces/ITrackSizeImpl.hpp"

extern "C" {
  #include <mad.h>
}

#include "visibility.hpp"

namespace NMM {
  class MPEGAudioDecodeNode :
    public GenericProcessorNode,
    public ISyncResetImpl,
    public ITrackImpl,
    public ITrackDurationImpl,
//    public ISeekReceiverImpl, 
    public ITrackSizeImpl
  {
    
  private:
    Timestamp timestamp;  //! The timestamp for the next output buffer.
    long int my_delay;    //! The duration of the next output buffer at audio sink.
    Timestamp in_buf_ts;  //! The timestamp of the last in_buffer with valid timestamp.

    unsigned int sample_rate;
    int channels;
    unsigned long bitrate;
    Time seek_time;

    ThreadMutex mad_mutex;
    
    bool first_timestamp;
    
    u_int64_t  track_size;

    void resetMP3(); //reset the library-Functions

    void setWOPInternal();
    
  protected:
    /**
    * >begin: Structures for MAD mpeg audio decoder
    */
    struct mad_stream stream;
    struct mad_frame  frame;
    struct mad_synth  synth;
    /* > end */

    /* size of our extra buffer space */
    int             fragment_size;

    /* bytes that could not decoded because data was needed (stream end) */
    int             rest_length;

    /* current length of incoming buffer */
    int             cur_buffer_length;

    /* pointer to end of audio stream data */
    unsigned char*  cur_buffer_end;

    /* pointer to begin of audio stream data */
    unsigned char*  tmpbuffer;

    /* size of tmpbuffer */
    int             inbuffer_size;

    /* track duration in seconds */
    u_int32_t track_duration;

    /* indicates when a trackDuration event should be sent */
    bool send_track_duration;

    virtual Result doInit();
    virtual Result doDeinit();
    virtual Result doInitOutput();
    virtual Message *processBuffer( Buffer *in_buffer);

    /**
     * reset workingflag and some variables
     */
    virtual Result doFlush();

    /**
     * Resets the parameters of timestamp computation.
     * The next outgoing buffer will have a stream_counter of 0.
     * If no input timestamp is present, it will also have a 
     * sync_time of 0.
     * MPEGAudioDecodeNode puts a timestamp in every outgoing buffer,
     * so the is_valid-flag in every timestamp is initialized to true.
     */
    virtual Result syncReset();
    
    // ITrack interface
    virtual Result startTrack(const string &file_name);
    virtual Result endTrack();
    
//    //ISeekReviecerInterface
//    virtual Result seeked(const u_int64_t& filepos);
    
    virtual Result doSetFormat(const Format& format);
    
    //! new seek method
    Result eventSeek(Interval& i, Time& t, nmm_int32& num_bytes);

    //from ITrackSizeImpl
    Result trackDuration(const Interval& i);
    
    Result trackSize(const nmm_uint64& bytes);
    
   public:
    MPEGAudioDecodeNode( const char * = "MPEGAudioDecodeNode", StreamQueue::Mode = StreamQueue::MODE_SUSPEND, int = 20);
    virtual ~MPEGAudioDecodeNode();

  };

}

#include "nmm/nmm_suffix.hpp"

#endif //NMM_MPEGAUDIODECODENODE_HPP

