#ifndef iphone_MediaPlayer
#define iphone_MediaPlayer

#import "c_ptr.h"
#import <string>
#import <list>

#import <AudioToolbox/AudioToolbox.h>
#import <AudioToolbox/AudioConverter.h>
#import <AudioUnit/AUComponent.h>
#import <AudioUnit/AUComponent.h>

extern "C"
{
#include "libavutil/fifo.h"
}


#import "Mutex.h"
#import "vn_player.h"
#import "VnPlayer.h"

@interface CallBackCommonParams : NSObject
{
	struct vn_player_frame_t *frame;
	struct vn_player_cache_boundaries_t *bounds;
	VN_PLAYER_STREAM_STATE *state;
	struct vn_player_result_status_t *status;
    struct vn_player_stream_info_t *stream_info;
}

- (void) reset;

@property (nonatomic, assign) struct vn_player_frame_t *frame;
@property (nonatomic, assign) struct vn_player_cache_boundaries_t* bounds;
@property (nonatomic, assign) VN_PLAYER_STREAM_STATE *state;
@property (nonatomic, assign) struct vn_player_result_status_t *status;
@property (nonatomic, assign) struct vn_player_stream_info_t *stream_info;
@end

namespace videonext { namespace media { namespace iphone {	
	
class MediaPlayer 
{
public:
	MediaPlayer(const std::string &url, VnPlayer *outputView);
	
	virtual ~MediaPlayer();

	void open();
    
    void play();

	void resume(int direction);
	
	void pause();
	
	void teardown();
	
	void moveToTimestamp(time_t ts);
	
private:
	static void new_frame(const vn_player_frame_t*, const vn_player_cache_boundaries_t*, void *client_data);
	
	static void buffer_changed(const vn_player_cache_boundaries_t*, void *client_data);  
	
	static void state_changed(VN_PLAYER_STREAM_STATE, const vn_player_result_status_t*, void *client_data);
	
	static void new_stream(const vn_player_stream_info_t*, void *client_data); 
	
	static void stream_removed(const vn_player_stream_info_t*, void *client_data); 
	
	static void msg_log(const char *msg, void *client_data);
	
	
private:
	std::string url_;
	VnPlayer *view_;
	CallBackCommonParams *params_;
	
private:
	struct vn_player_config_t conf_;	
	struct vn_player_env_t *env_; 
	struct vn_player_context_t *ctx_;
	
private: // audio support
	AudioComponentInstance audioUnit_;
	AudioStreamBasicDescription audioFormat_;
	AVFifoBuffer *audioInputBuffer_;
	Cond audioInputBufferMutex_;
	
private:
	void initAudioOutput(const vn_player_stream_info_t *streamInfo) throw (std::runtime_error);

	static OSStatus playbackCallback(void *opaque, 
									 AudioUnitRenderActionFlags *ioActionFlags, 
									 const AudioTimeStamp *inTimeStamp, 
									 UInt32 inBusNumber, 
									 UInt32 inNumberFrames, 
									 AudioBufferList *ioData); 

};

#define VN_CHECK_OSSTATUS_THROW_EXCEPTION(status, exception_class, format_str, ...) \
{                                                                       \
if (status != noErr)                                                 \
{                                                                    \
char err_str[1024];                                               \
\
snprintf(err_str, sizeof err_str,                                 \
"%s %d OSStatus failed: %d (\"%c%c%c%c\") " format_str,   \
__FILE__, __LINE__,                                      \
(unsigned)status,                                        \
((char*)&status)[3], ((char*)&status)[2], ((char*)&status)[1], ((char*)&status)[0], \
##__VA_ARGS__);                                          \
\
throw exception_class(err_str);                                   \
}                                                                    \
}
    
#define VN_CHECK_OSSTATUS(status, format_str, ...)                      \
{                                                                       \
if (status != noErr)                                                 \
{                                                                    \
char err_str[1024];                                               \
\
snprintf(err_str, sizeof err_str,                                 \
"%s %d OSStatus failed: %d (\"%c%c%c%c\") " format_str,   \
__FILE__, __LINE__,                                      \
(unsigned)status,                                        \
((char*)&status)[3], ((char*)&status)[2], ((char*)&status)[1], ((char*)&status)[0], \
##__VA_ARGS__);                                          \
\
fprintf(stderr, err_str);                                \
}                                                                    \
}

    
}}}

#endif
