//fformat.c:

/*
 *      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.
 *
 */

#include "rpld.h"

static struct {
 int          id;
 const char * name;
 const char * ext;
} ff_plf[] = {
 {RPLD_FF_PLF_RPLD,  "rpld",  "rpldpl"},
 {RPLD_FF_PLF_VCLT,  "vclt",  "vclt"  },
 {RPLD_FF_PLF_PLS,   "pls",   "pls"   },
 {RPLD_FF_PLF_M3U,   "m3u",   "m3u"   },
 {RPLD_FF_PLF_XSPF,  "xspf",  "xspf"  },
 {RPLD_FF_PLF_PLAIN, "plain", NULL    },
 {RPLD_FF_PLF_URAS,  "uras",  "xml"   },
 {-1, NULL, NULL}
};

int          fformat_str2plf(const char * str) {
 int i;

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

 for (i = 0; ff_plf[i].id != -1; i++)
  if ( !strcasecmp(str, ff_plf[i].name) )
   return ff_plf[i].id;

 roar_err_set(ROAR_ERROR_NOENT);
 return -1;
}

const char * fformat_plf2str(int plf) {
 int i;

 for (i = 0; ff_plf[i].id != -1; i++)
  if ( ff_plf[i].id == plf )
   return ff_plf[i].name;

 roar_err_set(ROAR_ERROR_NOENT);
 return NULL;
}

static struct {
 int format;
 int  (*open)    (struct fformat_handle * handle);
 void (*close    )(struct fformat_handle * handle);
 int  (*pl_export)(struct fformat_handle * handle, struct roar_vio_calls * vio, struct rpld_playlist  * pl);
 int  (*pl_import)(struct fformat_handle * handle, struct roar_vio_calls * vio, struct rpld_playlist  * pl);
 int  (*pl_update)(struct fformat_handle * handle, struct roar_vio_calls * vio, struct rpld_playlist  * pl);
} ff_handles[] = {
 {RPLD_FF_PLF_VCLT,  NULL, NULL, ff_vclt_pl_export,  ff_vclt_pl_import,  NULL},
 {RPLD_FF_PLF_PLAIN, NULL, NULL, ff_plain_pl_export, ff_plain_pl_import, NULL},
 {RPLD_FF_PLF_M3U,   NULL, NULL, ff_m3u_pl_export,   ff_m3u_pl_import,   NULL},
 {RPLD_FF_PLF_RPLD,  NULL, NULL, ff_rpld_pl_export,  ff_rpld_pl_import,  NULL},
 {RPLD_FF_PLF_PLS,   NULL, NULL, ff_pls_pl_export,   NULL,               NULL},
#ifdef HAVE_LIB_XML2
 {RPLD_FF_PLF_XSPF,  NULL, NULL, ff_xspf_pl_export,  ff_xspf_pl_import,  NULL},
 {RPLD_FF_PLF_URAS,  NULL, NULL, ff_uras_pl_export,  ff_uras_pl_import,  NULL},
#endif
 {-1, NULL, NULL, NULL, NULL, NULL}
};

struct fformat_handle * fformat_handle_new(int format) {
 struct fformat_handle * ret;

 int i;

 for (i = 0; ff_handles[i].format != -1; i++) {
  if ( ff_handles[i].format == format ) {
   if ( (ret = roar_mm_malloc(sizeof(struct fformat_handle))) == NULL )
    return NULL;

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

   ret->format   = format;
   ret->table_id = i;

   if ( ff_handles[i].open != NULL ) {
    if ( ff_handles[i].open(ret) == -1 ) {
     roar_mm_free(ret);
     return NULL;
    }
   }

   return ret;
  }
 }

 return NULL;
}

void                    fformat_handle_close(struct fformat_handle * handle) {
 if ( handle == NULL )
  return;

 if ( ff_handles[handle->table_id].close != NULL ) {
  ff_handles[handle->table_id].close(handle);
 }

 roar_mm_free(handle);
}

int                     fformat_playlist_export(struct fformat_handle * handle,
                                                struct roar_vio_calls * vio,
                                                struct rpld_playlist  * pl) {
 if ( ff_handles[handle->table_id].pl_export == NULL )
  return -1;

 return ff_handles[handle->table_id].pl_export(handle, vio, pl);
}

int                     fformat_playlist_import(struct fformat_handle * handle,
                                                struct roar_vio_calls * vio,
                                                struct rpld_playlist  * pl) {
 struct rpld_playlist * tmp_pl;
 int ret;

 if ( ff_handles[handle->table_id].pl_import == NULL ) {
  roar_err_set(ROAR_ERROR_NOTSUP);
  return -1;
 }

 tmp_pl = rpld_pl_new();
 if ( tmp_pl == NULL )
  return -1;

 yield_watchdog_stop();
 yield_auto(RPLD_YIELD_START, RPLD_YIELD_TASK_PLAYBACK, RPLD_YIELD_TASK_NETWORK, RPLD_YIELD_NONBLOCK);
 ret = ff_handles[handle->table_id].pl_import(handle, vio, tmp_pl);
 yield_auto(RPLD_YIELD_STOP, RPLD_YIELD_TASK_PLAYBACK, RPLD_YIELD_TASK_NETWORK, RPLD_YIELD_NONBLOCK);
 yield_watchdog_start();

 if ( ret == 0 ) {
  ret = rpld_pl_merge(pl, tmp_pl);
 }

 if ( ret == -1 ) {
  rpld_pl_unref(tmp_pl);
 }

 return ret;
}

int                     fformat_playlist_update(struct fformat_handle * handle,
                                                struct roar_vio_calls * vio,
                                                struct rpld_playlist  * pl) {
 if ( ff_handles[handle->table_id].pl_update == NULL )
  return -1;

 return ff_handles[handle->table_id].pl_update(handle, vio, pl);
}

//ll
