xspf_c  1.2.0
xspf_c.cpp
Go to the documentation of this file.
1 /*
2  * xspf_c - Simple C interface for libxspf
3  *
4  * Copyright (C) 2007, Ed Schouten / Xiph.Org Foundation
5  * Copyright (C) 2008, Sebastian Pipping / Xiph.Org Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer.
15  *
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials
19  * provided with the distribution.
20  *
21  * * Neither the name of the Xiph.Org Foundation nor the names of
22  * its contributors may be used to endorse or promote products
23  * derived from this software without specific prior written
24  * permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37  * OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  * Ed Schouten <ed@fxq.nl>
40  * Sebastian Pipping <sping@xiph.org>
41  */
47 #include <xspf/XspfIndentFormatter.h>
48 #include <xspf/XspfProps.h>
49 #include <xspf/XspfReader.h>
50 #include <xspf/XspfReaderCallback.h>
51 #include <xspf/XspfTrack.h>
52 #include <xspf/XspfWriter.h>
53 #include <cstring>
54 
55 extern "C" {
56 #include "xspf_c.h"
57 }
58 
59 using namespace Xspf;
60 
65 class XspfCReaderCallback : public XspfReaderCallback {
66 private:
77 
81  void addTrack(XspfTrack *track);
85  void setProps(XspfProps *props);
86 public:
94  virtual ~XspfCReaderCallback();
95 };
96 
98 {
99  this->list = list;
100  newtrack = &list->tracks;
101 }
102 
104 {
105  /* Null-terminate the tracks list */
106  *newtrack = NULL;
107 }
108 
109 void
111 {
112  xspf_mvalue **newmv;
113  char *str;
114 
115  /* Append new item to the track list */
116  *newtrack = new xspf_track;
117 
118  (*newtrack)->creator = track->stealCreator();
119  (*newtrack)->title = track->stealTitle();
120  (*newtrack)->album = track->stealAlbum();
121  (*newtrack)->duration = track->getDuration();
122  (*newtrack)->tracknum = track->getTrackNum();
123  (*newtrack)->pdata = NULL;
124 
125  /* Locations */
126  newmv = &(*newtrack)->locations;
127  while ((str = track->stealFirstLocation()) != NULL) {
128  *newmv = new xspf_mvalue;
129  (*newmv)->value = str;
130  (*newmv)->pdata = NULL;
131 
132  /* On to the next location */
133  newmv = &(*newmv)->next;
134  }
135  *newmv = NULL;
136 
137  /* Identifiers */
138  newmv = &(*newtrack)->identifiers;
139  while ((str = track->stealFirstIdentifier()) != NULL) {
140  *newmv = new xspf_mvalue;
141  (*newmv)->value = str;
142  (*newmv)->pdata = NULL;
143 
144  /* On to the next location */
145  newmv = &(*newmv)->next;
146  }
147  *newmv = NULL;
148 
149  /* Clean up and move to the next track */
150  delete track;
151  newtrack = &(*newtrack)->next;
152 }
153 
154 void
156 {
157  list->license = props->stealLicense();
158  list->location = props->stealLocation();
159  list->identifier = props->stealIdentifier();
160 
161  delete props;
162 }
163 
167 static void
169 {
170  struct xspf_mvalue *nmv;
171 
172  for (; mv != NULL; mv = nmv) {
173  /* Back-up pointer */
174  nmv = mv->next;
175  delete [] mv->value;
176  delete mv;
177  }
178 }
179 
180 /*
181  * Public C interface
182  */
183 
184 extern "C" struct xspf_list *
185 xspf_parse(char const *filename, char const *baseuri)
186 {
187  XspfReader read;
188  xspf_list *ret;
189 
190  /* Allocate empty playlist */
191  ret = new xspf_list;
192 
193  /* Fill the list with parser results */
194  XspfCReaderCallback readcb(ret);
195  if (read.parseFile(filename, &readcb, baseuri) == XSPF_READER_SUCCESS) {
196  /* Success */
197  return (ret);
198  } else {
199  /* Malformed/non-existent list */
200  delete ret;
201  return (NULL);
202  }
203 }
204 
205 extern "C" struct xspf_list *
206 xspf_parse_memory(char const *memory, int len_bytes, char const *baseuri)
207 {
208  XspfReader read;
209  xspf_list *ret;
210 
211  /* Allocate empty playlist */
212  ret = new xspf_list;
213 
214  /* Fill the list with parser results */
215  XspfCReaderCallback readcb(ret);
216  if (read.parseMemory(memory, len_bytes, &readcb, baseuri) == XSPF_READER_SUCCESS) {
217  /* Success */
218  return (ret);
219  } else {
220  /* Malformed/non-existent list */
221  delete ret;
222  return (NULL);
223  }
224 }
225 
226 extern "C" struct xspf_list *
227 xspf_new(void)
228 {
229  xspf_list *ret;
230 
231  ret = new xspf_list;
232  ret->license = NULL;
233  ret->location = NULL;
234  ret->identifier = NULL;
235  ret->tracks = NULL;
236  ret->pdata = NULL;
237 
238  return (ret);
239 }
240 
241 extern "C" void
242 xspf_free(struct xspf_list *list)
243 {
244  xspf_track *tr, *ntr;
245 
246  delete [] list->license;
247  delete [] list->location;
248  delete [] list->identifier;
249 
250  for (tr = list->tracks; tr != NULL; tr = ntr) {
251  /* Back-up pointer */
252  ntr = tr->next;
253 
254  delete [] tr->creator;
255  delete [] tr->title;
256  delete [] tr->album;
257 
260 
261  delete tr;
262  }
263 
264  delete list;
265 }
266 
267 extern "C" void
268 xspf_setvalue(char **str, char const *nstr)
269 {
270  /* Delete old string */
271  delete [] *str;
272 
273  if (nstr == NULL) {
274  /* Unset value */
275  *str = NULL;
276  } else {
277  /* Copy value */
278  size_t len;
279  len = strlen(nstr) + 1;
280  *str = new char[len];
281  strcpy(*str, nstr);
282  }
283 }
284 
285 extern "C" struct xspf_mvalue *
287 {
288  xspf_mvalue *ret;
289 
290  ret = new xspf_mvalue;
291  ret->value = NULL;
292  ret->pdata = NULL;
293  ret->next = *mvalue;
294  *mvalue = ret;
295 
296  return (ret);
297 }
298 
299 extern "C" struct xspf_track *
301 {
302  xspf_track *ret;
303 
304  ret = new xspf_track;
305  ret->creator = NULL;
306  ret->title = NULL;
307  ret->album = NULL;
308  ret->duration = -1;
309  ret->tracknum = -1;
310  ret->locations = NULL;
311  ret->identifiers = NULL;
312  ret->pdata = NULL;
313  ret->next = *track;
314  *track = ret;
315 
316  return (ret);
317 }
318 
319 int
320 xspf_write(struct xspf_list *list, char const *filename, char const *baseuri)
321 {
322  xspf_track *strack;
323  xspf_mvalue *smvalue;
324  XspfIndentFormatter formatter(-2);
325  int error;
326  XspfWriter * const writer = XspfWriter::makeWriter(formatter,
327  baseuri, XspfWriter::NO_XML_BASE, &error);
328  if (writer == NULL) {
329  return error;
330  }
331 
332  /* Playlist properties */
333  {
334  XspfProps props;
335  props.lendLicense(list->license);
336  props.lendLocation(list->location);
337  props.lendIdentifier(list->identifier);
338  writer->setProps(props);
339  }
340 
341  XSPF_LIST_FOREACH_TRACK(list, strack) {
342  /* Tracks */
343  XspfTrack track;
344  track.lendCreator(strack->creator);
345  track.lendTitle(strack->title);
346  track.lendAlbum(strack->album);
347  track.setDuration(strack->duration);
348  track.setTrackNum(strack->tracknum);
349 
350  /* Track locations and identifiers */
351  XSPF_TRACK_FOREACH_LOCATION(strack,smvalue)
352  track.lendAppendLocation(smvalue->value);
353  XSPF_TRACK_FOREACH_IDENTIFIER(strack, smvalue)
354  track.lendAppendIdentifier(smvalue->value);
355 
356  writer->addTrack(track);
357  }
358 
359  int const res = writer->writeFile(filename);
360  delete writer;
361  return res;
362 }
void xspf_setvalue(char **str, char const *nstr)
Set or overwrite a value in the xspf_list, xspf_track or xspf_mvalue structures. Passing NULL will un...
Definition: xspf_c.cpp:268
void * pdata
Private data that can be freely used.
Definition: xspf_c.h:141
int tracknum
Track number.
Definition: xspf_c.h:94
Linked list for values inside tracks or lists with string values.
Definition: xspf_c.h:54
struct xspf_mvalue * identifiers
Unique track identifiers.
Definition: xspf_c.h:103
struct xspf_track * xspf_new_track_before(struct xspf_track **track)
Insert a new track to the linked list before the specified one. This routine can also be used to inse...
Definition: xspf_c.cpp:300
XspfCReaderCallback(xspf_list *list)
Create callback interface for filling a xspf_list.
Definition: xspf_c.cpp:97
char * license
Playlist&#39;s license.
Definition: xspf_c.h:123
void addTrack(XspfTrack *track)
Callback which adds tracks to the xspf_list.
Definition: xspf_c.cpp:110
Single track in an XSPF list.
Definition: xspf_c.h:73
Xspf list reading callback, which stores data in a specific C-style Xspf list.
Definition: xspf_c.cpp:65
xspf_list * list
The C-style Xspf list the tracks should be appended to.
Definition: xspf_c.cpp:71
int duration
Track duration in milliseconds.
Definition: xspf_c.h:90
struct xspf_list * xspf_new(void)
Create a new empty XSPF playlist.
Definition: xspf_c.cpp:227
struct xspf_track * tracks
Linked list of tracks inside the playlist.
Definition: xspf_c.h:136
Simple libxspf C bindings.
void setProps(XspfProps *props)
Callback which sets properties in the xspf_list.
Definition: xspf_c.cpp:155
char * album
Album or collection of origin.
Definition: xspf_c.h:85
Parsed XSPF file.
Definition: xspf_c.h:119
void xspf_free(struct xspf_list *list)
Free the parser results.
Definition: xspf_c.cpp:242
void * pdata
Private data that can be freely used.
Definition: xspf_c.h:113
char * identifier
Playlist&#39;s unique indentifier.
Definition: xspf_c.h:131
char * title
Track&#39;s display name.
Definition: xspf_c.h:81
#define XSPF_TRACK_FOREACH_IDENTIFIER(t, i)
Easy interface for walking through identifiers.
Definition: xspf_c.h:157
virtual ~XspfCReaderCallback()
Finalize the xspf_list.
Definition: xspf_c.cpp:103
struct xspf_mvalue * next
Pointer to next object in the list.
Definition: xspf_c.h:62
void * pdata
Private data that can be freely used.
Definition: xspf_c.h:67
xspf_track ** newtrack
Pointer to the `next&#39; field in the last inserted item for improving append speed. ...
Definition: xspf_c.cpp:76
char * location
Playlist&#39;s file location.
Definition: xspf_c.h:127
#define XSPF_LIST_FOREACH_TRACK(l, t)
Easy interface for walking through tracks.
Definition: xspf_c.h:147
struct xspf_list * xspf_parse_memory(char const *memory, int len_bytes, char const *baseuri)
Parse an XSPF file from memory.
Definition: xspf_c.cpp:206
char * creator
Track&#39;s creator.
Definition: xspf_c.h:77
struct xspf_list * xspf_parse(char const *filename, char const *baseuri)
Parse an XSPF file by filename.
Definition: xspf_c.cpp:185
#define XSPF_TRACK_FOREACH_LOCATION(t, l)
Easy interface for walking through locations.
Definition: xspf_c.h:152
struct xspf_mvalue * locations
Track&#39;s file locations.
Definition: xspf_c.h:99
int xspf_write(struct xspf_list *list, char const *filename, char const *baseuri)
Write the Xspf playlist to a file.
Definition: xspf_c.cpp:320
struct xspf_track * next
Pointer to next track.
Definition: xspf_c.h:108
static void xspf_mvalue_free(struct xspf_mvalue *mv)
Deallocate all objects in a xspf_mvalue linked list.
Definition: xspf_c.cpp:168
char * value
Value of the current list entry.
Definition: xspf_c.h:58
struct xspf_mvalue * xspf_new_mvalue_before(struct xspf_mvalue **mvalue)
Insert a new mvalue to the linked list before the specified one. This routine can also be used to ins...
Definition: xspf_c.cpp:286