//backend.c:

/*
 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-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.
 *
 */

#include "rpld.h"

static struct roar_kstore * backend_store = NULL;
static  int                 global_codecbl[PLAYBACK_MAX_CODECBL];

int backend_init(void) {
 size_t i;

 if ( backend_store != NULL )
  return 0;

 for (i = 0; i < PLAYBACK_MAX_CODECBL; i++) {
  global_codecbl[i] = -1;
 }

 backend_store = roar_kstore_new(-1, (int(*)(void*))backend_ref, (int(*)(void*))backend_unref, NULL);
 if ( backend_store == NULL )
  return -1;

 return 0;
}

int backend_free(void) {
 if ( roar_kstore_unref(backend_store) == -1 )
  return -1;

 backend_store = NULL;
 return 0;
}

struct rpld_backend * backend_get_connection(const char * name) {
 return backend_get_connection2(name, 0);
}

struct rpld_backend * backend_get_connection2(const char * name, int allow_stub) {
 struct rpld_backend * ret = NULL;
 const char * server;
 size_t i;
 int err;

 if ( name == NULL )
  name = BACKEND_DEFAULT_NAME;

 if ( backend_store != NULL ) {
  ret = roar_kstore_get(backend_store, name);
  if ( ret != NULL )
   return ret; 
 }

 ret = roar_mm_malloc(sizeof(struct rpld_backend));
 if ( ret == NULL )
  return NULL;

 memset(ret, 0, sizeof(struct rpld_backend));

 ret->refc  = 1;
 ret->flags = 0;
 for (i = 0; i < PLAYBACK_MAX_CODECBL; i++) {
  ret->codecbl[i] = -1;
 }

 if ( !strcmp(name, BACKEND_DEFAULT_NAME) ) {
  server = NULL;
 } else {
  server = name;
 }

 if ( roar_simple_connect(&(ret->con), server, APPLICATION_NAME) == -1 ) {
  if ( allow_stub ) {
   roar_connect_none(&(ret->con));
  } else {
   err = roar_error;
   roar_mm_free(ret);
   roar_error = err;
   return NULL;
  }
 } else {
  ret->flags |= BACKEND_FLAG_CONNECTED;
 }

 if ( backend_store != NULL ) {
  ROAR_DBG("backend_get_connection2(name=?, allow_stub=%i): name='%s'", allow_stub, name);
  if ( roar_kstore_add(backend_store, ret, name) == -1 ) {
   err = roar_error;
   if ( ret->flags & BACKEND_FLAG_CONNECTED )
    roar_disconnect(&(ret->con));
   roar_mm_free(ret);
   roar_error = err;
   return NULL;
  }
 }

 return ret;
}

int backend_ref(struct rpld_backend * backend) {
 if ( backend == NULL ) {
  roar_err_set(ROAR_ERROR_FAULT);
  return -1;
 }

 backend->refc++;

 return 0;
}

int backend_unref(struct rpld_backend * backend) {
 if ( backend == NULL ) {
  roar_err_set(ROAR_ERROR_FAULT);
  return -1;
 }

 backend->refc--;

 if ( backend->refc )
  return 0;

 if ( backend->flags & BACKEND_FLAG_CONNECTED )
  roar_disconnect(&(backend->con));

 roar_mm_free(backend);

 return 0;
}

const char * backend_get_name(struct rpld_backend * backend) {
 const char * ret;

 if ( backend == NULL ) {
  roar_err_set(ROAR_ERROR_FAULT);
  return NULL;
 }

 if ( !(backend->flags & BACKEND_FLAG_CONNECTED) )
  return roar_kstore_name(backend_store, backend);

 ret = roar_get_connection_server(&(backend->con));

 if ( ret == NULL )
  return BACKEND_DEFAULT_NAME;

 return ret;
}

int backend_blacklist_codec(struct rpld_backend * backend, int codec) {
 int i;

 if ( backend == NULL ) {
  roar_err_set(ROAR_ERROR_FAULT);
  return -1;
 }

 for (i = 0; i < PLAYBACK_MAX_CODECBL; i++) {
  if ( backend->codecbl[i] == -1 ) {
   backend->codecbl[i] = codec;
   return 0;
  }
 }

 roar_err_set(ROAR_ERROR_NOSPC);
 return -1;
}

int backend_blacklist_codec_global(int codec) {
 int i;

 for (i = 0; i < PLAYBACK_MAX_CODECBL; i++) {
  if ( global_codecbl[i] == -1 ) {
   global_codecbl[i] = codec;
   return 0;
  }
 }

 roar_err_set(ROAR_ERROR_NOSPC);
 return -1;
}

int backend_blacklist_check_codec(struct rpld_backend * backend, int codec) {
 int i;

 if ( backend == NULL ) {
  roar_err_set(ROAR_ERROR_FAULT);
  return -1;
 }

 if ( codec == -1 ) {
  roar_err_set(ROAR_ERROR_INVAL);
  return 1;
 }

 for (i = 0; i < PLAYBACK_MAX_CODECBL; i++) {
  if ( global_codecbl[i] == codec ) {
   return 1;
  }
 }

 for (i = 0; i < PLAYBACK_MAX_CODECBL; i++) {
  if ( backend->codecbl[i] == codec ) {
   return 1;
  }
 }

 return 0;
}

//ll
