xspf_c  1.2.0
xspf_c.cpp
Go to the documentation of this file.
00001 /*
00002  * xspf_c - Simple C interface for libxspf
00003  *
00004  * Copyright (C) 2007, Ed Schouten / Xiph.Org Foundation
00005  * Copyright (C) 2008, Sebastian Pipping / Xiph.Org Foundation
00006  * All rights reserved.
00007  *
00008  * Redistribution  and use in source and binary forms, with or without
00009  * modification,  are permitted provided that the following conditions
00010  * are met:
00011  *
00012  *     * Redistributions   of  source  code  must  retain  the   above
00013  *       copyright  notice, this list of conditions and the  following
00014  *       disclaimer.
00015  *
00016  *     * Redistributions  in  binary  form must  reproduce  the  above
00017  *       copyright  notice, this list of conditions and the  following
00018  *       disclaimer   in  the  documentation  and/or  other  materials
00019  *       provided with the distribution.
00020  *
00021  *     * Neither  the name of the Xiph.Org Foundation nor the names of
00022  *       its  contributors may be used to endorse or promote  products
00023  *       derived  from  this software without specific  prior  written
00024  *       permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT
00028  * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS
00029  * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE
00030  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00031  * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES
00032  * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00033  * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00034  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00035  * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)
00036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00037  * OF THE POSSIBILITY OF SUCH DAMAGE.
00038  *
00039  * Ed Schouten <ed@fxq.nl>
00040  * Sebastian Pipping <sping@xiph.org>
00041  */
00047 #include <xspf/XspfIndentFormatter.h>
00048 #include <xspf/XspfProps.h>
00049 #include <xspf/XspfReader.h>
00050 #include <xspf/XspfReaderCallback.h>
00051 #include <xspf/XspfTrack.h>
00052 #include <xspf/XspfWriter.h>
00053 #include <cstring>
00054 
00055 extern "C" {
00056 #include "xspf_c.h"
00057 }
00058 
00059 using namespace Xspf;
00060 
00065 class XspfCReaderCallback : public XspfReaderCallback {
00066 private:
00071         xspf_list *list;
00076         xspf_track **newtrack;
00077 
00081         void addTrack(XspfTrack *track);
00085         void setProps(XspfProps *props);
00086 public:
00090         XspfCReaderCallback(xspf_list *list);
00094         virtual ~XspfCReaderCallback();
00095 };
00096 
00097 XspfCReaderCallback::XspfCReaderCallback(xspf_list *list)
00098 {
00099         this->list = list;
00100         newtrack = &list->tracks;
00101 }
00102 
00103 XspfCReaderCallback::~XspfCReaderCallback()
00104 {
00105         /* Null-terminate the tracks list */
00106         *newtrack = NULL;
00107 }
00108 
00109 void
00110 XspfCReaderCallback::addTrack(XspfTrack *track)
00111 {
00112         xspf_mvalue **newmv;
00113         char *str;
00114 
00115         /* Append new item to the track list */
00116         *newtrack = new xspf_track;
00117 
00118         (*newtrack)->creator = track->stealCreator();
00119         (*newtrack)->title = track->stealTitle();
00120         (*newtrack)->album = track->stealAlbum();
00121         (*newtrack)->duration = track->getDuration();
00122         (*newtrack)->tracknum = track->getTrackNum();
00123         (*newtrack)->pdata = NULL;
00124 
00125         /* Locations */
00126         newmv = &(*newtrack)->locations;
00127         while ((str = track->stealFirstLocation()) != NULL) {
00128                 *newmv = new xspf_mvalue;
00129                 (*newmv)->value = str;
00130                 (*newmv)->pdata = NULL;
00131 
00132                 /* On to the next location */
00133                 newmv = &(*newmv)->next;
00134         }
00135         *newmv = NULL;
00136 
00137         /* Identifiers */
00138         newmv = &(*newtrack)->identifiers;
00139         while ((str = track->stealFirstIdentifier()) != NULL) {
00140                 *newmv = new xspf_mvalue;
00141                 (*newmv)->value = str;
00142                 (*newmv)->pdata = NULL;
00143 
00144                 /* On to the next location */
00145                 newmv = &(*newmv)->next;
00146         }
00147         *newmv = NULL;
00148 
00149         /* Clean up and move to the next track */
00150         delete track;
00151         newtrack = &(*newtrack)->next;
00152 }
00153 
00154 void
00155 XspfCReaderCallback::setProps(XspfProps *props)
00156 {
00157         list->license = props->stealLicense();
00158         list->location = props->stealLocation();
00159         list->identifier = props->stealIdentifier();
00160 
00161         delete props;
00162 }
00163 
00167 static void
00168 xspf_mvalue_free(struct xspf_mvalue *mv)
00169 {
00170         struct xspf_mvalue *nmv;
00171 
00172         for (; mv != NULL; mv = nmv) {
00173                 /* Back-up pointer */
00174                 nmv = mv->next;
00175                 delete [] mv->value;
00176                 delete mv;
00177         }
00178 }
00179 
00180 /*
00181  * Public C interface
00182  */
00183 
00184 extern "C" struct xspf_list *
00185 xspf_parse(char const *filename, char const *baseuri)
00186 {
00187         XspfReader read;
00188         xspf_list *ret;
00189 
00190         /* Allocate empty playlist */
00191         ret = new xspf_list;
00192 
00193         /* Fill the list with parser results */
00194         XspfCReaderCallback readcb(ret);
00195         if (read.parseFile(filename, &readcb, baseuri) == XSPF_READER_SUCCESS) {
00196                 /* Success */
00197                 return (ret);
00198         } else {
00199                 /* Malformed/non-existent list */
00200                 delete ret;
00201                 return (NULL);
00202         }
00203 }
00204 
00205 extern "C" struct xspf_list *
00206 xspf_parse_memory(char const *memory, int len_bytes, char const *baseuri)
00207 {
00208         XspfReader read;
00209         xspf_list *ret;
00210 
00211         /* Allocate empty playlist */
00212         ret = new xspf_list;
00213 
00214         /* Fill the list with parser results */
00215         XspfCReaderCallback readcb(ret);
00216         if (read.parseMemory(memory, len_bytes, &readcb, baseuri) == XSPF_READER_SUCCESS) {
00217                 /* Success */
00218                 return (ret);
00219         } else {
00220                 /* Malformed/non-existent list */
00221                 delete ret;
00222                 return (NULL);
00223         }
00224 }
00225 
00226 extern "C" struct xspf_list *
00227 xspf_new(void)
00228 {
00229         xspf_list *ret;
00230 
00231         ret = new xspf_list;
00232         ret->license = NULL;
00233         ret->location = NULL;
00234         ret->identifier = NULL;
00235         ret->tracks = NULL;
00236         ret->pdata = NULL;
00237 
00238         return (ret);
00239 }
00240 
00241 extern "C" void
00242 xspf_free(struct xspf_list *list)
00243 {
00244         xspf_track *tr, *ntr;
00245 
00246         delete [] list->license;
00247         delete [] list->location;
00248         delete [] list->identifier;
00249 
00250         for (tr = list->tracks; tr != NULL; tr = ntr) {
00251                 /* Back-up pointer */
00252                 ntr = tr->next;
00253 
00254                 delete [] tr->creator;
00255                 delete [] tr->title;
00256                 delete [] tr->album;
00257 
00258                 xspf_mvalue_free(tr->locations);
00259                 xspf_mvalue_free(tr->identifiers);
00260 
00261                 delete tr;
00262         }
00263 
00264         delete list;
00265 }
00266 
00267 extern "C" void
00268 xspf_setvalue(char **str, char const *nstr)
00269 {
00270         /* Delete old string */
00271         delete [] *str;
00272 
00273         if (nstr == NULL) {
00274                 /* Unset value */
00275                 *str = NULL;
00276         } else {
00277                 /* Copy value */
00278                 size_t len;
00279                 len = strlen(nstr) + 1;
00280                 *str = new char[len];
00281                 strcpy(*str, nstr);
00282         }
00283 }
00284 
00285 extern "C" struct xspf_mvalue *
00286 xspf_new_mvalue_before(struct xspf_mvalue **mvalue)
00287 {
00288         xspf_mvalue *ret;
00289 
00290         ret = new xspf_mvalue;
00291         ret->value = NULL;
00292         ret->pdata = NULL;
00293         ret->next = *mvalue;
00294         *mvalue = ret;
00295 
00296         return (ret);
00297 }
00298 
00299 extern "C" struct xspf_track *
00300 xspf_new_track_before(struct xspf_track **track)
00301 {
00302         xspf_track *ret;
00303 
00304         ret = new xspf_track;
00305         ret->creator = NULL;
00306         ret->title = NULL;
00307         ret->album = NULL;
00308         ret->duration = -1;
00309         ret->tracknum = -1;
00310         ret->locations = NULL;
00311         ret->identifiers = NULL;
00312         ret->pdata = NULL;
00313         ret->next = *track;
00314         *track = ret;
00315 
00316         return (ret);
00317 }
00318 
00319 int
00320 xspf_write(struct xspf_list *list, char const *filename, char const *baseuri)
00321 {
00322         xspf_track *strack;
00323         xspf_mvalue *smvalue;
00324         XspfIndentFormatter formatter(-2);
00325         int error;
00326         XspfWriter * const writer = XspfWriter::makeWriter(formatter,
00327                         baseuri, XspfWriter::NO_XML_BASE, &error);
00328         if (writer == NULL) {
00329                 return error;
00330         }
00331 
00332         /* Playlist properties */
00333         {
00334                 XspfProps props;
00335                 props.lendLicense(list->license);
00336                 props.lendLocation(list->location);
00337                 props.lendIdentifier(list->identifier);
00338                 writer->setProps(props);
00339         }
00340 
00341         XSPF_LIST_FOREACH_TRACK(list, strack) {
00342                 /* Tracks */
00343                 XspfTrack track;
00344                 track.lendCreator(strack->creator);
00345                 track.lendTitle(strack->title);
00346                 track.lendAlbum(strack->album);
00347                 track.setDuration(strack->duration);
00348                 track.setTrackNum(strack->tracknum);
00349 
00350                 /* Track locations and identifiers */
00351                 XSPF_TRACK_FOREACH_LOCATION(strack,smvalue)
00352                         track.lendAppendLocation(smvalue->value);
00353                 XSPF_TRACK_FOREACH_IDENTIFIER(strack, smvalue)
00354                         track.lendAppendIdentifier(smvalue->value);
00355 
00356                 writer->addTrack(track);
00357         }
00358 
00359         int const res = writer->writeFile(filename);
00360         delete writer;
00361         return res;
00362 }
 All Classes Files Functions Variables Defines