//rpldplugin.h:

/*
 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2014
 *
 *  This file is part of RoarAudio PlayList Daemon,
 *  a playlist management daemon for RoarAudio.
 *  See README for details.
 *
 *  This file is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 3
 *  as published by the Free Software Foundation.
 *
 *  RoarAudio 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 this software; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

#ifndef _RPLDPLUGIN_H_
#define _RPLDPLUGIN_H_

#include <roaraudio.h>

#define RPLDPH_APPNAME    "rpld " ROAR_VSTR_ROARAUDIO
#define RPLDPH_ABIVERSION "0.1.5"

#define RPLDPH_CHECK_VERSIONS() ROAR_DL_PLUGIN_CHECK_VERSIONS(RPLDPH_APPNAME, RPLDPH_ABIVERSION)

// forward declerations:
struct rpld_playlist_entry;
struct rpld_backend;
struct rpld_playlist_pointer;

// normal declerations:
typedef unsigned int rpld_pli_t;
#define RPLD_PLI_INVALID ((rpld_pli_t)-1)
struct rpld_fformat_handle;
typedef struct rpld_fformat_handle * rpld_fformat_t;
typedef int64_t rpld_maxint_t;

typedef enum {
 RPLDPH_CONFIG_KEY_MAX_CLIENTS = 16,
 RPLDPH_CONFIG_KEY_MAX_PLAYLISTS,
 RPLDPH_CONFIG_KEY_MAX_LISTENS,
 RPLDPH_CONFIG_KEY_MAX_CODECBL,
 RPLDPH_CONFIG_KEY_MAX_POINTER,

 RPLDPH_CONFIG_KEY_DEFAULT_BACKEND,
 RPLDPH_CONFIG_KEY_DEFAULT_PLF,

 RPLDPH_CONFIG_KEY_APPNAME,
 RPLDPH_CONFIG_KEY_APPVENDOR,
} rpldph_config_key_t;

typedef enum {
 RPLDPH_FALSE  =  0,
 RPLDPH_TRUE   =  1,
 RPLDPH_TOGGLE =  2,
 RPLDPH_ASK    = -2,
 RPLDPH_ERROR  = -1
} rpldph_bool_t;

// binargv tree:
struct __rpldph_functions_config {
 ssize_t (*_get_limit)(rpldph_config_key_t key);
 const char * (*_get_value)(rpldph_config_key_t key);
};

// This structure allows access to libroar's (common) memory functions without linking it.
struct __rpldph_functions_memory {
 void * (*_calloc)(size_t nmemb, size_t size);
 void * (*_malloc)(size_t size);
 void   (*_free)(void *ptr);
 void * (*_realloc)(void *ptr, size_t size);
 char * (*_strdup)(const char *s);
};

// This structure allows access to libroar's (common) error functions without linking it.
struct __rpldph_functions_error {
 int          (*_get)(void);
 void         (*_set)(const int error);
 const char * (*_error2str)(const int error);
};

struct __rpldph_functions_control {
 void (*_exit)(void);
 const struct roar_server_info * (*_serverinfo)(void);
};

struct __rpldph_functions_ple {
 struct rpld_playlist_entry * (*_new)         (void);
 void                         (*_free)        (struct rpld_playlist_entry * plent);
 struct rpld_playlist_entry * (*_copy)        (struct rpld_playlist_entry * plent);
 int                          (*_set_res)     (struct rpld_playlist_entry * plent, const char * file, int codec, time_t length);
 int                          (*_set_meta)    (struct rpld_playlist_entry * plent, struct roar_keyval * kv, ssize_t len);
 const char *                 (*_get_meta)    (struct rpld_playlist_entry * plent, const char * key);
 int                          (*_set_meta_int)(struct rpld_playlist_entry * plent, const char * key, rpld_maxint_t val);
 rpld_maxint_t                (*_get_meta_int)(struct rpld_playlist_entry * plent, const char * key);
 int                          (*_get_codec)   (struct rpld_playlist_entry * plent);
 time_t                       (*_get_length)  (struct rpld_playlist_entry * plent);
 int                          (*_set_uuid)    (struct rpld_playlist_entry * plent, const char * uuid);
 const char *                 (*_get_uuid)    (struct rpld_playlist_entry * plent, char * buf);
 int                          (*_set_likeness)(struct rpld_playlist_entry * plent, float likeness);
 int                          (*_inc_likeness)(struct rpld_playlist_entry * plent, float likeness);
 float                        (*_get_likeness)(struct rpld_playlist_entry * plent);
 struct rpld_playlist_entry * (*_get_next)    (struct rpld_playlist_entry * plent);
 int                          (*_set_offset)  (struct rpld_playlist_entry * plent, int_least32_t   start, int_least32_t   end);
 int                          (*_get_offset)  (struct rpld_playlist_entry * plent, int_least32_t * start, int_least32_t * end);
};

struct __rpldph_functions_playlist {
 rpld_pli_t   (*_new)  (const char * name, rpld_pli_t parent);
 void         (*_free) (rpld_pli_t pl);
 int          (*_flush)(rpld_pli_t pl);
 int          (*_merge)(rpld_pli_t pl, rpld_pli_t tm);
 int          (*_set_name)(rpld_pli_t pl, const char * name);
 const char * (*_get_name)(rpld_pli_t pl);
 int          (*_set_parent)(rpld_pli_t pl, rpld_pli_t parent);
 rpld_pli_t   (*_get_parent)(rpld_pli_t pl);
 rpld_pli_t   (*_get_by_name)(const char * name);
 ssize_t      (*_get_num)(rpld_pli_t pl);

 int                          (*_push)     (rpld_pli_t pl, struct rpld_playlist_entry * plent);
 int                          (*_unshift)  (rpld_pli_t pl, struct rpld_playlist_entry * plent);
 struct rpld_playlist_entry * (*_pop)      (rpld_pli_t pl);
 struct rpld_playlist_entry * (*_shift)    (rpld_pli_t pl);
 int                          (*_add)      (rpld_pli_t pl, struct rpld_playlist_entry * plent, ssize_t pos);

 struct rpld_playlist_entry * (*_get_first)(rpld_pli_t pl);
};

struct __rpldph_functions_history {
 int     (*_set_size)(rpld_pli_t history, ssize_t size);
 ssize_t (*_get_size)(rpld_pli_t history);
};

struct __rpldph_functions_plp {
 struct rpld_playlist_pointer * (*_new)     (rpld_pli_t playlist, const char * type, const void * argp);
 int                            (*_ref)     (struct rpld_playlist_pointer * plp);
 int                            (*_unref)   (struct rpld_playlist_pointer * plp);
 int                            (*_copy)    (struct rpld_playlist_pointer ** dst,
                                             struct rpld_playlist_pointer * src);
 struct rpld_playlist_entry   * (*_search)  (struct rpld_playlist_pointer * plp);
};

struct __rpldph_functions_playback {
 int  (*_play)(rpld_pli_t queue);
 int  (*_next)(rpld_pli_t queue);
 int  (*_prev)(rpld_pli_t queue);
 int  (*_stop)(rpld_pli_t queue);
 int  (*_pause)(rpld_pli_t queue, rpldph_bool_t how);

 rpldph_bool_t  (*_is_playing)(rpld_pli_t queue);
 rpldph_bool_t  (*_is_paused) (rpld_pli_t queue);
 rpldph_bool_t  (*_is_queue)  (rpld_pli_t queue);

 float (*_get_volume)(rpld_pli_t queue);
 int   (*_set_volume)(rpld_pli_t queue, float volume);

 void (*_set_role)(rpld_pli_t queue, const int role);

 struct rpld_playlist_entry * (*_get_ple)(rpld_pli_t queue);
 size_t (*_get_mduc)(rpld_pli_t queue);
 const struct roar_stream * (*_get_stream)(rpld_pli_t queue);
};

struct __rpldph_functions_store {
 int (*_save)(void);
 int (*_load)(void);
};

struct __rpldph_functions_backend {
 struct rpld_backend * (*_get_connection)(const char * name);

 int (*_ref)(struct rpld_backend * backend);
 int (*_unref)(struct rpld_backend * backend);

 const char * (*_get_name)(struct rpld_backend * backend);
 struct roar_connection * (*_get_con)(struct rpld_backend * backend); // need to roar_connectionunref() after use.

 int (*_blacklist_codec)(struct rpld_backend * backend, int codec);
 int (*_blacklist_codec_global)(int codec);
 int (*_blacklist_check_codec)(struct rpld_backend * backend, int codec);
};

struct __rpldph_functions_client {
// enum rpld_client_acclev client_get_acclev(int id);
// int  client_set_acclev(int id, enum rpld_client_acclev acclev, int setter);
// int  client_inc_acclev(int id, int inc, int setter);

 int  (*_set_name)(int id, const char * name);
 const char * (*_get_name)(int id);

 int  (*_set_playlist)(int id, rpld_pli_t pl);
 rpld_pli_t (*_get_playlist)(int id);
 int  (*_set_queue)(int id, rpld_pli_t pl);
 rpld_pli_t (*_get_queue)(int id);

 int  (*_str2proto)(const char * str);
 const char * (*_proto2str)(const int proto);
// enum rpld_client_acclev (*_str2acclev)(const char * str);
};

struct __rpldph_functions_fformat {
 int          (*_str2plf)(const char * str);
 const char * (*_plf2str)(int plf);

 rpld_fformat_t (*_handle_new)(int format);
 void           (*_handle_close)(rpld_fformat_t handle);

 int            (*_playlist_export)(rpld_fformat_t handle,
                                    struct roar_vio_calls * vio,
                                    rpld_pli_t pl);

 int            (*_playlist_import)(rpld_fformat_t handle,
                                    struct roar_vio_calls * vio,
                                    rpld_pli_t pl);
};

struct __rpldph_functions_pointer {
 char                         * (*_get_name)(const int pointer, const rpld_pli_t queue, const int client);
 int                            (*_parse_name)(int * pointer, rpld_pli_t * queue, int * client, int client_hint, const char * name);
 int                            (*_is_set)(const int pointer, const rpld_pli_t queue, const int client);
 struct rpld_playlist_pointer * (*_get)(const int pointer, const rpld_pli_t queue, const int client);
 struct rpld_playlist_pointer * (*_get_by_name)(const char * name, int client_hint);
 int                            (*_set)(const int pointer, const rpld_pli_t queue, const int client, struct rpld_playlist_pointer * plp);
 int                            (*_set_by_name)(const char * name, const int client_hint, struct rpld_playlist_pointer * plp);
 struct rpld_playlist_entry   * (*_search)(const int pointer, const rpld_pli_t queue, const int client);
};

struct __rpldph_functions_yield {
 void (*_ay_trigger)(void);
 void (*_ay_pause)(void);
 void (*_ay_unpause)(void);
 void (*_watchdog_trigger)(void);
};

struct __rpldph_functions {
 struct __rpldph_functions_config config;

 // libroar's (common) memory functions (libroar/memmgr.h)
 struct __rpldph_functions_memory memory;

 // libroar's (common) error functions (libroar/error.h)
 struct __rpldph_functions_error error;

// rpld.h
 struct __rpldph_functions_control control;

// playlist.h
 struct __rpldph_functions_ple ple;
 struct __rpldph_functions_playlist playlist;
 struct __rpldph_functions_history history;
 struct __rpldph_functions_plp plp;

// playback.h
 struct __rpldph_functions_playback playback;

// store.h
 struct __rpldph_functions_store store;

// backend.h
 struct __rpldph_functions_backend backend;

// client.h
 struct __rpldph_functions_client client;

// fformat.h
 struct __rpldph_functions_fformat fformat;

// pointer.h
 struct __rpldph_functions_pointer pointer;

// yield.h
 struct __rpldph_functions_yield yield;
};

struct __rpldph_binargv {
 const struct __rpldph_functions functions;
};

#define __rpldph_export_func(prefix,func)     (((struct __rpldph_binargv*)para->binargv)->functions.prefix.func)
#define __rpldph_export0(prefix,func)         __rpldph_export_func(prefix,func)()
#define __rpldph_export1(prefix,func,arg)     __rpldph_export_func(prefix,func)(arg)
#define __rpldph_exportn(prefix,func,arg,...) __rpldph_export_func(prefix,func)(arg, __VA_ARGS__)

#define rpldph_config_get_limit(arg) __rpldph_export1(config,_get_limit,arg)
#define rpldph_config_get_value(arg) __rpldph_export1(config,_get_value,arg)

#define rpldph_memory_calloc(arg,...) __rpldph_exportn(memory,_calloc,arg,__VA_ARGS__)
#define rpldph_memory_malloc(arg) __rpldph_export1(memory,_malloc,arg)
#define rpldph_memory_free(arg) __rpldph_export1(memory,_free,arg)
#define rpldph_memory_realloc(arg,...) __rpldph_exportn(memory,_realloc,arg,__VA_ARGS__)
#define rpldph_memory_strdup(arg) __rpldph_export1(memory,_strdup,arg)

#define rpldph_error_get() __rpldph_export0(error,_get)
#define rpldph_error_set(arg) __rpldph_export1(error,_set,arg)
#define rpldph_error_error2str(arg) __rpldph_export1(error,_error2str,arg)

#define rpldph_control_exit() __rpldph_export0(control,_exit)
#define rpldph_control_serverinfo() __rpldph_export0(control,_serverinfo)

#define rpldph_ple_new()     __rpldph_export0(ple,_new)
#define rpldph_ple_free(arg) __rpldph_export1(ple,_free,arg)
#define rpldph_ple_copy(arg) __rpldph_export1(ple,_copy,arg)
#define rpldph_ple_set_res(arg,...) __rpldph_exportn(ple,_set_res,arg,__VA_ARGS__)
#define rpldph_ple_set_meta(arg,...) __rpldph_exportn(ple,_set_meta,arg,__VA_ARGS__)
#define rpldph_ple_get_meta(arg,...) __rpldph_exportn(ple,_get_meta,arg,__VA_ARGS__)
#define rpldph_ple_set_meta_int(arg,...) __rpldph_exportn(ple,_set_meta_int,arg,__VA_ARGS__)
#define rpldph_ple_get_meta_int(arg,...) __rpldph_exportn(ple,_get_meta_int,arg,__VA_ARGS__)
#define rpldph_ple_get_codec(arg) __rpldph_export1(ple,_get_codec,arg)
#define rpldph_ple_get_time(arg) __rpldph_export1(ple,_get_time,arg)
#define rpldph_ple_set_uuid(arg,...) __rpldph_exportn(ple,_set_uuid,arg,__VA_ARGS__)
#define rpldph_ple_get_uuid(arg,...) __rpldph_exportn(ple,_get_uuid,arg,__VA_ARGS__)
#define rpldph_ple_set_likeness(arg,...) __rpldph_exportn(ple,_set_likeness,arg,__VA_ARGS__)
#define rpldph_ple_inc_likeness(arg,...) __rpldph_exportn(ple,_inc_likeness,arg,__VA_ARGS__)
#define rpldph_ple_get_likeness(arg) __rpldph_export1(ple,_get_likeness,arg)
#define rpldph_ple_get_next(arg) __rpldph_export1(ple,_get_next,arg)
#define rpldph_ple_set_offset(arg,...) __rpldph_exportn(ple,_set_offset,arg,__VA_ARGS__)
#define rpldph_ple_get_offset(arg,...) __rpldph_exportn(ple,_get_offset,arg,__VA_ARGS__)

#define rpldph_playlist_new(arg,...) __rpldph_exportn(playlist,_new,arg,__VA_ARGS__)
#define rpldph_playlist_free(arg) __rpldph_export1(playlist,_free,arg)
#define rpldph_playlist_flush(arg) __rpldph_export1(playlist,_flush,arg)
#define rpldph_playlist_merge(arg,...) __rpldph_exportn(playlist,_merge,arg,__VA_ARGS__)
#define rpldph_playlist_set_name(arg,...) __rpldph_exportn(playlist,_set_name,arg,__VA_ARGS__)
#define rpldph_playlist_get_name(arg) __rpldph_export1(playlist,_get_name,arg)
#define rpldph_playlist_set_parent(arg,...) __rpldph_exportn(playlist,_set_parent,arg,__VA_ARGS__)
#define rpldph_playlist_get_parent(arg) __rpldph_export1(playlist,_parent,arg)
#define rpldph_playlist_get_by_name(arg) __rpldph_export1(playlist,_get_by_name,arg)
#define rpldph_playlist_get_num(arg) __rpldph_export1(playlist,_get_num,arg)
#define rpldph_playlist_push(arg,...) __rpldph_exportn(playlist,_push,arg,__VA_ARGS__)
#define rpldph_playlist_unshift(arg,...) __rpldph_exportn(playlist,_unshift,arg,__VA_ARGS__)
#define rpldph_playlist_pop(arg,...) __rpldph_exportn(playlist,_pop,arg,__VA_ARGS__)
#define rpldph_playlist_shift(arg,...) __rpldph_exportn(playlist,_shift,arg,__VA_ARGS__)
#define rpldph_playlist_add(arg,...) __rpldph_exportn(playlist,_add,arg,__VA_ARGS__)
#define rpldph_playlist_get_first(arg) __rpldph_export1(playlist,_get_first,arg)

#define rpldph_history_set_size(arg,...) __rpldph_exportn(history,_set_size,arg,__VA_ARGS__)
#define rpldph_history_get_size(arg) __rpldph_export1(history,_get_size,arg)

#define rpldph_plp_new(arg,...) __rpldph_exportn(plp,_new,arg,__VA_ARGS__)
#define rpldph_plp_ref(arg) __rpldph_export1(plp,_ref,arg)
#define rpldph_plp_unref(arg) __rpldph_export1(plp,_unref,arg)
#define rpldph_plp_copy(arg,...) __rpldph_exportn(plp,_copy,arg,__VA_ARGS__)
#define rpldph_plp_search(arg) __rpldph_export1(plp,_search,arg)

#define rpldph_playback_play(arg) __rpldph_export1(playback,_play,arg)
#define rpldph_playback_next(arg) __rpldph_export1(playback,_next,arg)
#define rpldph_playback_prev(arg) __rpldph_export1(playback,_prev,arg)
#define rpldph_playback_stop(arg) __rpldph_export1(playback,_stop,arg)
#define rpldph_playback_pause(arg,...) __rpldph_exportn(playback,_pause,arg,__VA_ARGS__)

#define rpldph_playback_is_playing(arg) __rpldph_export1(playback,_is_playing,arg)
#define rpldph_playback_is_paused(arg) __rpldph_export1(playback,_is_paused,arg)
#define rpldph_playback_is_queue(arg) __rpldph_export1(playback,_is_queue,arg)
#define rpldph_playback_get_volume(arg) __rpldph_export1(playback,_get_volume,arg)
#define rpldph_playback_set_volume(arg,...) __rpldph_exportn(playback,_set_volume,arg,__VA_ARGS__)
#define rpldph_playback_set_role(arg,...) __rpldph_exportn(playback,_set_role,arg,__VA_ARGS__)

#define rpldph_playback_get_ple(arg) __rpldph_export1(playback,_get_ple,arg)
#define rpldph_playback_get_mduc(arg) __rpldph_export1(playback,_get_mduc,arg)
#define rpldph_playback_get_stream(arg) __rpldph_export1(playback,_get_stream,arg)

#define rpldph_store_save() __rpldph_export0(store,_save)
#define rpldph_store_load() __rpldph_export0(store,_load)

#define rpldph_backend_get_connection(arg) __rpldph_export1(backend,_get_connection,arg)
#define rpldph_backend_ref(arg) __rpldph_export1(backend,_ref,arg)
#define rpldph_backend_unref(arg) __rpldph_export1(backend,_unref,arg)
#define rpldph_backend_get_name(arg) __rpldph_export1(backend,_get_name,arg)
#define rpldph_backend_get_con(arg) __rpldph_export1(backend,_get_con,arg)
#define rpldph_backend_blacklist_codec(arg,...) __rpldph_exportn(backend,_blacklist_codec,arg,__VA_ARGS__)
#define rpldph_backend_blacklist_check_codec(arg,...) __rpldph_exportn(backend,_blacklist_codec,arg,__VA_ARGS__)

#define rpldph_client_set_name(arg,...) __rpldph_exportn(client,_set_name,arg,__VA_ARGS__)
#define rpldph_client_get_name(arg) __rpldph_export1(client,_get_name,arg)
#define rpldph_client_set_playlist(arg,...) __rpldph_exportn(client,_set_playlist,arg,__VA_ARGS__)
#define rpldph_client_get_playlist(arg) __rpldph_export1(client,_get_playlist,arg)
#define rpldph_client_set_queue(arg,...) __rpldph_exportn(client,_set_queue,arg,__VA_ARGS__)
#define rpldph_client_get_queue(arg) __rpldph_export1(client,_get_queue,arg)
#define rpldph_client_str2proto(arg) __rpldph_export1(client,_str2proto,arg)
#define rpldph_client_proto2str(arg) __rpldph_export1(client,_proto2str,arg)

#define rpldph_fformat_str2plf(arg) __rpldph_export1(fformat,_str2plf,arg)
#define rpldph_fformat_plf2str(arg) __rpldph_export1(fformat,_plf2str,arg)
#define rpldph_fformat_handle_new(arg) __rpldph_export1(fformat,_handle_new,arg)
#define rpldph_fformat_handle_close(arg) __rpldph_export1(fformat,_handle_close,arg)
#define rpldph_fformat_playlist_export(arg,...) __rpldph_exportn(fformat,_playlist_export,arg,__VA_ARGS__)
#define rpldph_fformat_playlist_import(arg,...) __rpldph_exportn(fformat,_playlist_import,arg,__VA_ARGS__)

#define rpldph_pointer_get_name(arg,...) __rpldph_exportn(pointer,_get_name,arg,__VA_ARGS__)
#define rpldph_pointer_parse_name(arg,...) __rpldph_exportn(pointer,_parse_name,arg,__VA_ARGS__)
#define rpldph_pointer_is_set(arg,...) __rpldph_exportn(pointer,_is_set,arg,__VA_ARGS__)
#define rpldph_pointer_get(arg,...) __rpldph_exportn(pointer,_get,arg,__VA_ARGS__)
#define rpldph_pointer_get_by__name(arg,...) __rpldph_exportn(pointer,_get_by_name,arg,__VA_ARGS__)
#define rpldph_pointer_set(arg,...) __rpldph_exportn(pointer,_set,arg,__VA_ARGS__)
#define rpldph_pointer_set_by_name(arg,...) __rpldph_exportn(pointer,_set_by_name,arg,__VA_ARGS__)
#define rpldph_pointer_search(arg,...) __rpldph_exportn(pointer,_search,arg,__VA_ARGS__)

#define rpldph_yield_ay_trigger() __rpldph_export0(yield,_ay_trigger)
#define rpldph_yield_ay_pause() __rpldph_export0(yield,_ay_pause)
#define rpldph_yield_ay_unpause() __rpldph_export0(yield,_ay_unpause)
#define rpldph_yield_watchdog_trigger() __rpldph_export0(yield,_watchdog_trigger)

#endif

//ll
