/*
 *   MediaMVP Server Library
 *
 *   (C) 2004 Dominic Morris
 *
 *   $Id: libmvp.h,v 1.34 2004/10/24 11:37:37 dom Exp $
 *   $Date: 2004/10/24 11:37:37 $
 *
 *   This file contains all application accessible information
 */


#ifndef LIBMVP_H
#define LIBMVP_H

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/queue.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <resolv.h>
#include <netdb.h>
#include <float.h>
#include <math.h>
#include <ctype.h>
#include <sys/time.h>

#include <event.h>

#include "config.h"

/* Drag in some message types */
#include "msgs.h"

#include "keys.h"

#ifndef WIN32
enum { FALSE = 0, TRUE };
#endif



typedef struct _gui gui_t;
typedef struct _stream  stream_t;
typedef unsigned char bool_t;


/* dongle.c - all we need to expose here is the settings really... */
typedef struct {
    char      address[30];      /* Should be more than enough */
    int       tvmode;
    int       flickermode;
    int       aspectratio;
    int       videooutput;      /* Sent by client?!? */
    int       old_tvmode;       /* Used to assist auto switching */
    bool_t    inuse;
    gui_t    *gui;
    stream_t *stream;
} dongle_t;

typedef struct _surface surface_t;

/* Definition for header stripping */
typedef struct {
    unsigned char         tmp[100];
    size_t                tmplen;
    size_t                offset;
    unsigned char         pid;
} astrip_t;

extern void            audio_strip(astrip_t *astrip, unsigned char *buf, int buflen);



/* Application */
extern void            dongle_send_play(dongle_t *dongle, char *name);
extern void            dongle_send_message(dongle_t *dongle, int msgtype);
extern void            dongle_send_percent(dongle_t *dongle, int msgtype, int percent);
extern void            dongle_send_settings(dongle_t *dongle, int subcommand);
extern int             dongle_get_type(dongle_t *dongle);
extern int             dongle_get_lasttype(dongle_t *dongle);
extern void            dongle_update_screen(dongle_t *dongle);
extern char           *dongle_get_streamname(dongle_t *dongle);

/* surface.c */

/* Modes that we support */
typedef enum {
    MAP_YVU = 0,
    MAP_RGB,
    MAP_AYVU,
    MAP_ARGB,
} mapmode_t;
extern surface_t      *surface_alloc(int width, int depth, int bpp);
extern void            surface_dealloc(surface_t *surface);
extern void            surface_clear(surface_t *surface, uint32_t rgb);
extern void           *surface_map(surface_t *surface, mapmode_t mode, int *size);
extern unsigned int    surface_get_pixel(surface_t *surface,int x, int y);
extern void            surface_set_pixel(surface_t *surface, int x, int y, uint32_t rgb);
extern int             surface_get_dirty(surface_t *surface);
extern void            surface_set_dirty(surface_t *surface, int state);      
extern void            surface_blit(surface_t *dest, surface_t *src, int delta_x, int delta_y, int width, int depth);
extern int             surface_get_height(surface_t *surface);
extern int             surface_get_width(surface_t *surface);

/* Graphics routines - names may change? */
extern void            surface_draw_rectangle(surface_t *sfc, int x1, int y1, int x2, int y2, uint32_t colour);
extern void            surface_draw_ellipse(surface_t *sfc, int x1, int y1, int x2, int y2, uint32_t colour, int Quadrants);
extern void            surface_draw_line(surface_t *sfc, int x0, int y0, int x1, int y1, uint32_t colour);
extern void            surface_draw_round_rect(surface_t *sfc, int x, int y, int w, int d, int r, int t, uint32_t c, uint32_t b);


/* stream.c */
#define MEDIA_MASK       3
#define MEDIA_MPEG       1
#define MEDIA_MP3        2
#define MEDIA_JPEG       4
#define MEDIA_PICTURE    8       /* Generic picture type */

/* Modifiers */
#define MEDIA_LIVE      64
#define MEDIA_SOCKET   128






/* urlhandler.c  - fops has to passed through so that we can then call playlist_check on it and types get
 propogated about the place
*/
typedef struct _fops fops_t;
typedef void (*readready_cb)(void *);

struct _fops {
    char        *prefix;
    void      *(*open)(char *name, int *type, fops_t **fops_ptr, readready_cb cb, void *cb_ptr);
    void       (*close)(void *ptr);
    off_t      (*seek)(void *ptr, off_t offset, int whence);
    int        (*read)(void *ptr, unsigned char *buf, size_t buflen);
    int        (*info)(void *ptr, int command, void *args);
};

/* Commands for the info */
#define URLFILE_SIZE        1
#define URLFILE_NAME        2
#define URLFILE_LOCATION    3
#ifdef HAVE_LIBID3TAG
#define URLFILE_MP3TAG      4
#endif
#define URLFILE_MPEG_FRAME_RATE 5
#define URLFILE_IFRAME 6

typedef struct {
    int    count;
    off_t  start;
    size_t length;   
} gopseek_t;


/* Nasty function to determine info about playlists - check playlist.c for param details */
extern int        playlist_check(char *incoming_name, int fd, void *urlptr, int *filetype, void **return_ptr,
                                  fops_t **fops_ptr,readready_cb cb,void *cb_ptr);

extern void       urlhandler_add(char *prefix, fops_t *fops);


/* Error warning levels */
enum { MOO = 0, DEBUG, INFO, ERROR };
extern void            Dprintf(int level, char *fmt,...);
typedef struct _application application_t;

/* Starting up and shutting down the server */
typedef struct {
    uint32_t main_interfaceip;
    int      gui_port;
    int      stream_port;
    int      dongle_version;   
    int      mpeg_bufsize;
    int      mp3_bufsize;
    int      debug_level;
    FILE    *logfile;
    int    (*open)(dongle_t *dongle, application_t *app);
    int    (*authorise)(char *mac_address, uint32_t ipaddr, int connected);

} mvpinit_t;

#define MVPINIT_INITIALISER { 0, 5906, 6337, 21323, 200000, 4000, INFO }


struct _application {
    void     (*close)(application_t *);
    uint8_t *(*get_yvuy_surface)(application_t *, int *size);
    void     (*keypress)(application_t *, int keycode);
    void     (*ack)(application_t *app, int ackcode, unsigned char *buf, int buflen);
    int      gui_width;  /* Filled in by new_app */
    int      gui_depth;
    int      screen_width;
    int      screen_depth;
    void    *data;   /* Used to hold private data by the application 
*/
};





extern int        mediamvp_server_init(mvpinit_t *init);
extern void       mediamvp_server_stop();

extern int32_t    host_resolve(char *serv);


/* Some quite dirty media detection routines, buf should be at least 4 bytes long  */
extern int        file_get_type(char *filename);
extern int        file_get_type_fd(int fd, unsigned char *buf);


/* MP3 ID3 tag handling */
typedef struct _mp3info  mp3info_t;
#ifdef HAVE_LIBID3TAG
extern mp3info_t      *new_mp3info();
extern unsigned char  *mp3_get_title(mp3info_t *info);
extern unsigned char  *mp3_get_artist(mp3info_t *info);
extern unsigned char  *mp3_get_album(mp3info_t *info);
extern unsigned char  *mp3_get_track(mp3info_t *info);
extern unsigned char  *mp3_get_year(mp3info_t *info);
extern void            mp3_info_delete(mp3info_t *info);
extern mp3info_t      *mp3_get_info_fd(int mp3_fd);
extern mp3info_t      *mp3_get_info_file(char *mp3_filename);
#endif

/* MPEG Frame rate detection */
typedef struct _mpeginfo mpeginfo_t;

extern mpeginfo_t     *mpeg_get_info_fd(int mpeg_file);
extern mpeginfo_t     *mpeg_get_info_file(char *mpeg_filename);
extern int             mpeg_get_width(mpeginfo_t *info);
extern int             mpeg_get_height(mpeginfo_t *info);
extern int             mpeg_get_rate_index(mpeginfo_t *info);
extern void            delete_mpeg_info(mpeginfo_t *info);

/* threading compatibility - bit basic! */
#ifndef WIN32
#include <pthread.h>

typedef pthread_mutex_t mutex_t;
#define mutex_init(m,a)  pthread_mutex_init(m,a)
#define mutex_lock(m)    pthread_mutex_lock(m)
#define mutex_unlock(m)  pthread_mutex_unlock(m)
#define mutex_destroy(m) pthread_mutex_destroy(m)

#else
typedef void *mutex_t;
#define mutex_init(m,a)
#define mutex_lock(m)
#define mutex_unlock(m)
#define mutex_destroy(m)
#endif


#ifdef __cplusplus
}
#endif


#endif /* LIBMVP_H */
