/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: hxaudply.h,v 1.8.2.1 2004/07/09 02:08:04 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

#ifndef _HXAUPLY_H_
#define _HXAUPLY_H_

#include "hxaudtyp.h" 
#include "hxaudses.h" 

// forward decls
struct IHXAudioPlayerResponse;
struct IHXAudioStream;
struct IHXAudioHook;
struct IHXAudioStreamInfoResponse;
struct IHXScheduler;
struct IHXVolume;
struct IHXPreferences;
struct IHXAudioCrossFade;

typedef struct _HXAudioFormat HXAudioFormat;

class CHXAudioSession;
class CHXSimpleList;
class CHXAudioStream;

class Timeval;

#ifdef _MACINTOSH
extern BOOL gSoundCallbackTime;
#endif

/****************************************************************************
 *
 *  Class:
 *
 *      CHXAudioPlayer
 *
 *  Purpose:
 *
 *      PN implementation of audio player.
 *
 */
class CHXAudioPlayer: public IHXAudioPlayer,
#ifdef HELIX_FEATURE_VOLUME 
                      public IHXVolumeAdviseSink,
#endif 
                      public IHXAudioCrossFade,
                      public IHXCallback
{
private:
	LONG32				m_lRefCount;
	BOOL				m_bAdjustForRealAudio;
	HXAudioFormat			m_PlayerFmt;		// This players audio format
	IHXAudioPlayerResponse*	m_pPlayerResponse;	// Notification interface
	IHXScheduler*			m_pScheduler;
	IHXPreferences*		m_pPreferences;
	ULONG32				m_ulCurrentTime; 	// Current playback time 
	ULONG32				m_ulLastCurrentTimeReturned; 	
	ULONG32				m_ulLastDeviceTimeAdjusted;
	BOOL				m_bTimeReturned;
	BOOL				m_bDisableDeviceWrite;	// Don't write to audio device
	ULONG32				m_ulBytesPerGran; 	// Num bytesper granularity

	CHXSimpleList*			m_pStreamRespList;	// Stream response list

	ULONG32				m_ulASstartTime;	// This player's start time.
								// This is in audio session time.
	ULONG32				m_ulAPplaybackTime; 	// This player's playback time
								// within the timeline
	ULONG32				m_ulAPstartTime; 	// This player's playback start time
								// within the timeline.
	ULONG32				m_ulADresumeTime;	// This is the audio device time
								// when this player resumed.

	EPlayerState			m_eState;		// Status

        BOOL   				m_bPrefUse11khz;	// Sampling rate from prefs
        UINT16 				m_uPrefBitsPerSample;	// Bits per sample from prefs
        UINT16 				m_uPrefAudioQuality;	// Audio quality from prefs
	BOOL				m_bDisableWrite;
	BOOL				m_bIsResumed;
	UINT32				m_ulTimeAdjustDoneAt;
	UINT16				m_uVolume;
	BOOL				m_bMute;
	INT64				m_llLastWriteTime;
    
#ifdef HELIX_FEATURE_VOLUME        
        IHXVolume* m_pPlayerVolume;
#endif        

protected:
        ~CHXAudioPlayer();
	PRIVATE_DESTRUCTORS_ARE_NOT_A_CRIME

public:

	CHXAudioPlayer(CHXAudioSession* owner);

	void		    Close(void);

        //IHXCallback methods
        STDMETHOD(Func)(THIS);
        
	/*
 	 *	IUnknown methods
 	 */
	STDMETHOD(QueryInterface)   (THIS_
                                REFIID riid,
                                void** ppvObj);

	STDMETHOD_(ULONG32,AddRef)  (THIS);

	STDMETHOD_(ULONG32,Release) (THIS);

	/*
	 *      IHXAudioPlayer methods
	 */
	STDMETHOD(CreateAudioStream)	(THIS_
					IHXAudioStream**		pAudioStream
					);

	/* AddPostMixHook Interface is called by renderers to set a 
	 * post mix hook of the audio data.
	 */
        STDMETHOD(AddPostMixHook)(THIS_
				IHXAudioHook*		pHook,
				const BOOL		bDisableWrite,
				const BOOL		bFinal
				);
        STDMETHOD(RemovePostMixHook)(THIS_
				IHXAudioHook*		pHook
				);

#ifdef HELIX_FEATURE_VOLUME        
        // IHXVolumeAdviseSink methods
        inline STDMETHOD(OnVolumeChange)(THIS_ const UINT16 uVol )
        {
            m_uVolume = uVol;
            return HXR_OK;
        }
        
        inline STDMETHOD(OnMuteChange)(THIS_ const BOOL bMute )
        {
            m_bMute = bMute;
            return HXR_OK;
        }
        inline UINT16 GetVolume()
        {
            return m_bMute? 0 : m_uVolume;
        }
        
#endif        
        
	/************************************************************************
	*  Method:
	*      IHXAudioPlayer::GetAudioStreamCount
	*  Purpose:
	*		Get the number of audio streams currently active in the 
	*		audio player. Since streams can be added mid-presentation
	*		this function may return different values on different calls.
	*		If the user needs to know about all the streams as they get
	*		get added to the player, IHXAudioStreamInfoResponse should
	*		be implemented and passed in SetStreamInfoResponse.
	*/
	STDMETHOD_(UINT16,GetAudioStreamCount) (THIS);

	/* Get an audio stream from the stream list at position given.
	 */
        STDMETHOD_(IHXAudioStream*,GetAudioStream)(THIS_
				UINT16			uIndex
				);

	/* Set a stream info response. This is used to get the number
	 * of streams associated with this player.
	 */
        STDMETHOD(SetStreamInfoResponse)(THIS_
				IHXAudioStreamInfoResponse*	pResponse
				);

	/************************************************************************
	*  Method:
	*      IHXAudioPlayer::RemoveStreamInfoResponse
	*  Purpose:
	*	Remove stream info response that was added earlier
	*/
	STDMETHOD(RemoveStreamInfoResponse) (THIS_
				    IHXAudioStreamInfoResponse* /*IN*/ pResponse);

	/* Return the this player's volume interface. */
	STDMETHOD_(IHXVolume*, GetAudioVolume) 	(THIS);

	/* Return the session device volume interface. */
	STDMETHOD_(IHXVolume*, GetDeviceVolume) (THIS);

	/*
	 *  IHXAudioCrossFade methods
	 */

	/************************************************************************
	 *  Method:
	 *      IHXAudioCrossFade::CrossFade
	 *  Purpose:
	 *	Cross-fade two audio streams.
	 *	pStreamFrom		- Stream to be cross faded from
	 *	pStreamTo		- Stream to be cross faded to
	 *	ulFromCrossFadeStartTime- "From" Stream time when cross fade is 
	 *				  to be started
	 *	ulToCrossFadeStartTime	- "To" Stream time when cross fade is to 
	 *				  be started
	 *	ulCrossFadeDuration	- Duration over which cross-fade needs
	 *				      to be done
	 *	    
	 */
	STDMETHOD(CrossFade)	(THIS_
				IHXAudioStream* pStreamFrom,
				IHXAudioStream* pStreamTo,
				UINT32		 ulFromCrossFadeStartTime,
				UINT32		 ulToCrossFadeStartTime,
				UINT32		 ulCrossFadeDuration);

 	STDMETHOD(SetError)     (THIS_
 				    HX_RESULT theErr
 				    );
 
	/*
	 *   Other public methods.
	 */
	HX_RESULT	InitializeStructures	(void);

	HX_RESULT	Init	(
				IUnknown*		pContext
				);
	HX_RESULT	Setup(ULONG32 ulGranuarity);

	void		SetGranularity (
				const ULONG32 		ulGranularity
				);
	HX_RESULT	Resume(void);

	HX_RESULT	Pause(void);

	HX_RESULT	Stop	(
				const BOOL		bFlush
				);

	void		DonePlayback(void)   {m_bIsDonePlayback = TRUE;};
	BOOL		IsDonePlayback(void) {return m_bIsDonePlayback;};

	HX_RESULT	Seek	(
				const ULONG32		ulSeekTime
				);
	CHXAudioSession* GetOwner(void) 
				{ return m_Owner; };
	void		GetFormat( 
				HXAudioFormat*		pAudioFormat
				);
	CHXSimpleList*	GetStreamList(void) 
				{ 
				return m_pStreamList; 
				};

	HX_RESULT		OnTimeSync(
				ULONG32			ulCurrentTime
				);
	ULONG32		GetCurrentPlayBackTime(void);

	UINT16		GetStreamCount(void);

	/* Return the post process hook list. */
	CHXSimpleList*	GetPostMixHookList(void) 
				{ 
				return m_pPMixHookList; 
				};

	EPlayerState	GetState(void)
				{
				return m_eState;
				}

	void		StreamInitialized(CHXAudioStream* pAudioStream);
	BOOL		IsDisableWrite(void) {return m_bDisableWrite;};
	ULONG32		GetInitialPushdown(BOOL bAtStart = FALSE);

	void		SetLive(BOOL bIsLive);
	void		AudioFormatNowKnown(void);

	void		RegisterRealAudioStream  
			    (CHXAudioStream* pAudioStream);
	void		UnRegisterRealAudioStream
			    (CHXAudioStream* pAudioStream);

	INT64		GetLastAudioWriteTime(void) {return m_llLastWriteTime;};

	BOOL		IsThisAudioStream(IHXValues* pHeader);
	BOOL		IsAudioOnlyTrue(void);

	double		NumberOfBytesWritten();
	double		ConvertMsToBytes(UINT32 ulTime);
	void		UpdateStreamLastWriteTime();

	void		UpdateLastWriteTime(UINT32 ulGranularity)
			    {m_llLastWriteTime += (INT64) ulGranularity;};

	void		SaveLastNMilliSeconds(BOOL bSave, UINT32 ulNMilliSeconds);
	void		RewindPlayer(UINT32 ulTimeToRewind);
	void		DataInAudioDevice(BOOL bHasDataInAudioDevice) {m_bHasDataInAudioDevice = bHasDataInAudioDevice;};
	BOOL		HasDataInAudioDevice() {return m_bHasDataInAudioDevice;};

	HX_RESULT	SetSoundLevel(CHXSimpleList* pAudioStreamList, UINT16 uSoundLevel, BOOL bReflushAudioDevice);

        typedef enum
        {
            STR_REMOVE,
            STR_PAUSE,
            STR_RESUME,
            STR_SEEK,
            STR_STOP,
            STR_SETHINT
        } STREAM_ACTION;
        
        HX_RESULT ManageAudioStreams(CHXSimpleList* pStreamLst,
                                     STREAM_ACTION what,
                                     UINT32 ulTime = 0
                                     );
        

        
	HX_RESULT	AudioStreamStateChanged(EPlayerState eState);
	CHXAudioStream*	GetCHXAudioStream(UINT16 uIndex);

	BOOL		IsLastNMilliSecsToBeStored();

	HX_RESULT	ActualAddPostMixHook(IHXAudioHook* pHook,
	    				     const BOOL	    bDisableWrite,
					     const BOOL	    bFinal);
	HX_RESULT	ActualRemovePostMixHook(IHXAudioHook* pHook);

	UINT32		GetGranularity(void) { return m_ulGranularity; };
	BOOL		IsResumed(void) { return m_bIsResumed; };
	inline void     UseCoreThread()
        {
            m_Owner->UseCoreThread();
        }
        

	virtual HX_RESULT   _CreateAudioStream(IHXAudioStream** pAudioStream);
	virtual	HX_RESULT   ProcessAudioHook(PROCESS_ACTION action, 
					     IHXAudioHook* pAudioHook);
	virtual void	    ResetPlayer(void);

	friend class CHXAudioStream;

protected:
        ULONG32                 m_ulCallbackID;
	IUnknown*		m_pContext;
	BOOL			m_bInited;		// Initialized?
	BOOL			m_bHasStreams;		// Player has streams..
	BOOL			m_bIsLive;
	ULONG32			m_ulGranularity; 	// Playback granularity
	CHXAudioSession*	m_Owner;
	CHXSimpleList*		m_pStreamList;		
	CHXSimpleList*		m_pRealAudioStreamList;
	CHXSimpleList*		m_pPMixHookList;	// Post mix hooks
	HXAudioFormat		m_DeviceFmt;		// Audio device format
	Timeval*		m_pFakeAudioCBTime;
	ULONG32			m_ulLastFakeCallbackTime;
	ULONG32			m_ulIncreasingTimer;
	BOOL			m_bIsDonePlayback;
	BOOL			m_bIsFirstResume;
	BOOL			m_bCanBeRewound;
	BOOL			m_bHasDataInAudioDevice;

	void			OnTimerCallback();

	void		SetupStreams(void);
	void		AddStreams(void);
	void		RemoveStreams(void);
	UINT16		NumberOfResumedStreams(void);

	/* Get audio prefs.
	 */
	HX_RESULT	GetAudioPrefs(void);
	void		AdjustForRealAudio(void);

	HX_RESULT	ResumeFakeTimeline(void);
	HX_RESULT	StopFakeTimeline(void);
};

#endif /* HXAUPLY_H_ */
