xspf_c
1.2.0
|
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 }