//playlist.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 _RPLD_PLAYLIST_H_
#define _RPLD_PLAYLIST_H_

#define MAX_PLAYLISTS 64

#define RPLD_MAX_PLF_LEN    1024
#define RPLD_META_SHORT_LEN  384 /* 1024*3/8, well above the 255/256 limit of some applications */

#define RPLD_PL_MAGIC    0xD9

typedef unsigned int pli_t;
typedef uint64_t     ei_t;
typedef uint32_t     ei_short_t;
typedef uint32_t     discid_t;

// PLE flags:
#define RPLD_PLE_FLAG_NONE       0x0000
#define RPLD_PLE_FLAG_UNSKIPABLE 0x0001

// PLE Wallclock time parameters:
#define RPLD_PLE_WALLCLOCK_INVALID ((time_t)770248800L)

// PLE filter options:
#define RPLD_PLE_FILTER_NONE     0x0000
#define RPLD_PLE_FILTER_NORMKEY  0x0001 /* search in normal keys             */
#define RPLD_PLE_FILTER_EXTKEY   0x0002 /* search in extra keys              */
#define RPLD_PLE_FILTER_CASE     0x0004 /* search case sensetive             */
#define RPLD_PLE_FILTER_ANCHORB  0x0008 /* "begin" anchor: ^                 */
#define RPLD_PLE_FILTER_ANCHORE  0x0010 /* "end" anchor: $                   */
#define RPLD_PLE_FILTER_BNEEDLE  0x0020 /* needle is binary (uuid, GTN, ...) */

// ???:
#define RPLD_PL_FLAG_NONE        0x0000
#define RPLD_PL_FLAG_VIRTUAL     0x0001
#define RPLD_PL_FLAG_UNLINKED    0x0002

#define RPLD_PL_VIRT_DELETE      -1
#define RPLD_PL_VIRT_KEEP         0
#define RPLD_PL_VIRT_CREATE      +1

// PlayList SearchType
#define RPLD_PL_ST_NONE             0
#define RPLD_PL_ST_TRACKNUM_LONG    1
#define RPLD_PL_ST_TRACKNUM_SHORT   2
#define RPLD_PL_ST_UUID             3
#define RPLD_PL_ST_NUM              4
#define RPLD_PL_ST_LIKENESS         5
#define RPLD_PL_ST_RANDOM           6
#define RPLD_PL_ST_RANDOM_LIKENESS  7

// PlayList SearchOptions
#define RPLD_PL_SO_NONE             0x0000
#define RPLD_PL_SO_PREVIOUS         0x0001

typedef int_least32_t rpld_mus_t;

enum rpld_filename_type {
 RPLD_TYPE_ERROR = -1,
 RPLD_TYPE_UNKNOWN = 0,
 RPLD_TYPE_AUTOLOCATE = 1,
 RPLD_TYPE_STREAMURL,
 RPLD_TYPE_FILENAME,
 RPLD_TYPE_FILEURL
};

struct rpld_filename {
 char * filename;
 enum rpld_filename_type type;
};

struct rpld_playlist_entry {
/*
  trancknum:
   11223344 AABBCCDD

   11           8 Bit -> PID & 0xFF
   22           8 Bit -> Magic
   3344 AABBCC 40 Bit -> counter
   DD           8 Bit -> RAND()

  short:
   11223344

   11           8 Bit -> (PID & 0xFF) ^ ((counter & 0x00FF0000) >> 16)
   2233        16 Bit -> counter & 0xFFFF
   44           8 Bit -> RAND() ^ Magic
 */
 ei_t       global_tracknum;
 ei_short_t global_short_tracknum;
 roar_uuid_t uuid;
 unsigned int flags;
 time_t length;
 rpld_mus_t start; // start time (within the resource) in ms.
 rpld_mus_t end;   // end time (within the resource) in ms.
 time_t wallclock_start;
 struct roar_stream_rpg rpg;
 int codec;
 struct {
  struct rpld_filename * filenames;
  ssize_t num;
  ssize_t slots;
  char tantalos[48];
 } io;
 struct {
  char     album[RPLD_META_SHORT_LEN];
  char     title[RPLD_META_SHORT_LEN];
  char     artist[RPLD_MAX_PLF_LEN];
  char     performer[RPLD_MAX_PLF_LEN];
  char     version[RPLD_META_SHORT_LEN];
  int      genre;
  int      tracknum;
  discid_t discid;
  struct {
   struct roar_keyval * kv;
   ssize_t kvlen;
   void * kv_store;
   ssize_t kv_storelen;
  } extra;
 } meta;
 struct {
  struct rpld_playlist_entry * next;
 } list;
 float likeness;
};

struct rpld_playlist {
 size_t                       refc;
 struct rpld_playlist_entry * first;
 char                       * name;
 pli_t                        id;
 pli_t                        parent;
 unsigned int                 flags;
 volatile size_t              transactions;
 int                          policy;
 size_t                       size_hint;
 float                        likeness_hint;
 struct rpld_queue          * queue;
 ssize_t                      histsize;
};

struct rpld_playlist_search {
 int type;
 union {
  ei_t        long_tracknum;
  ei_short_t short_tracknum;
  roar_uuid_t          uuid;
  size_t                num;
  float            likeness;
  pli_t                  pl;
 } subject;
 unsigned int options;
};

struct rpld_playlist_pointer {
 size_t refc;
 struct rpld_playlist_search pls;
 struct {
  struct rpld_playlist       * pl;
  struct rpld_playlist_entry * ple;
 } hint;
};

extern struct rpld_playlist * g_playlists[MAX_PLAYLISTS];

struct rpld_playlist_entry * rpld_ple_new     (void);
void                         rpld_ple_free    (struct rpld_playlist_entry * plent);
struct rpld_playlist_entry * rpld_ple_copy    (struct rpld_playlist_entry * plent);

struct rpld_playlist_entry * rpld_ple_cut_out_next (struct rpld_playlist_entry * plent);

const char                 * rpld_ple_time_hr (const struct rpld_playlist_entry * plent);
int                          rpld_ple_set_time_hr (struct rpld_playlist_entry * plent, char * time);

enum rpld_filename_type      rpld_ple_get_filenametype(const char * type);

int                          rpld_ple_push_filename(struct rpld_playlist_entry * plent, const char * filename, enum rpld_filename_type type, int clear);
const char *                 rpld_ple_get_filename(struct rpld_playlist_entry * plent, ssize_t index, enum rpld_filename_type * type);
ssize_t                      rpld_ple_num_filename(const struct rpld_playlist_entry * plent);

//  SEARCHPLE {"search string"|0xdiscid|uuid} [{AS|IN} {ALL|TITLE|ARTIST|VERSION|FILENAME|DISCID|UUID|TAG:"Tagname"}] [FROM {"Name"|ID|ANY}]
int                          rpld_ple_filter  (struct rpld_playlist_entry * plent, const void * needle, const char * key, int options);

struct rpld_playlist       * rpld_pl_new      (void);
int                          rpld_pl_ref      (struct rpld_playlist * pl);
int                          rpld_pl_unref    (struct rpld_playlist * pl);
void                         rpld_pl_push     (struct rpld_playlist * pl, struct rpld_playlist_entry * plent);
void                         rpld_pl_add      (struct rpld_playlist * pl, struct rpld_playlist_entry * plent, ssize_t pos);
struct rpld_playlist_entry * rpld_pl_get_first(struct rpld_playlist * pl);
struct rpld_playlist_entry * rpld_pl_shift    (struct rpld_playlist * pl);
struct rpld_playlist_entry * rpld_pl_pop      (struct rpld_playlist * pl);
void                         rpld_pl_flush    (struct rpld_playlist * pl);
struct rpld_playlist_entry * rpld_pl_search   (struct rpld_playlist        * pl,
                                               struct rpld_playlist_search * search,
                                               struct rpld_playlist_entry  * pmatch);

int                          rpld_pl_virtual  (struct rpld_playlist * pl, int virt);

int                          rpld_pl_merge    (struct rpld_playlist * pl, struct rpld_playlist * tm);

int                          rpld_pl_set_name (struct rpld_playlist * pl, const char * name);
char *                       rpld_pl_get_name (struct rpld_playlist * pl);
int                          rpld_pl_set_id   (struct rpld_playlist * pl, pli_t id);
pli_t                        rpld_pl_get_id   (struct rpld_playlist * pl);
int                          rpld_pl_set_parent(struct rpld_playlist * pl, pli_t parent);
pli_t                        rpld_pl_get_parent(struct rpld_playlist * pl);
int                          rpld_pl_set_histsize(struct rpld_playlist * pl, ssize_t size);
ssize_t                      rpld_pl_get_histsize(struct rpld_playlist * pl);
int                          rpld_pl_register (struct rpld_playlist * pl);
int                          rpld_pl_register_id(struct rpld_playlist * pl, pli_t id);
int                          rpld_pl_unregister(struct rpld_playlist * pl);
struct rpld_playlist       * rpld_pl_get_by_id (pli_t id);
struct rpld_playlist       * rpld_pl_get_by_name(const char * name);

size_t                       rpld_pl_num      (struct rpld_playlist * pl);

struct rpld_playlist_pointer * rpld_plp_init    (struct rpld_playlist         * pl,
                                                 struct rpld_playlist_search  * pls);
int                            rpld_plp_ref     (struct rpld_playlist_pointer * plp);
int                            rpld_plp_unref   (struct rpld_playlist_pointer * plp);
int                            rpld_plp_copy    (struct rpld_playlist_pointer ** dst,
                                                 struct rpld_playlist_pointer * src);
struct rpld_playlist_entry   * rpld_plp_search  (struct rpld_playlist_pointer * plp);

#endif

//ll
