flac_metadata_object.c 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820
  1. /* libFLAC - Free Lossless Audio Codec library
  2. * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * - Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * - Neither the name of the Xiph.org Foundation nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #if HAVE_CONFIG_H
  32. # include <config.h>
  33. #endif
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include "flac_private_metadata.h"
  37. #include "flac_FLAC_assert.h"
  38. #include "flac_share_alloc.h"
  39. /****************************************************************************
  40. *
  41. * Local routines
  42. *
  43. ***************************************************************************/
  44. /* copy bytes:
  45. * from = NULL && bytes = 0
  46. * to <- NULL
  47. * from != NULL && bytes > 0
  48. * to <- copy of from
  49. * else ASSERT
  50. * malloc error leaves 'to' unchanged
  51. */
  52. static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
  53. {
  54. FLAC__ASSERT(0 != to);
  55. if(bytes > 0 && 0 != from) {
  56. FLAC__byte *x;
  57. if(0 == (x = (FLAC__byte*)safe_malloc_(bytes)))
  58. return false;
  59. memcpy(x, from, bytes);
  60. *to = x;
  61. }
  62. else {
  63. FLAC__ASSERT(0 == from);
  64. FLAC__ASSERT(bytes == 0);
  65. *to = 0;
  66. }
  67. return true;
  68. }
  69. #if 0 /* UNUSED */
  70. /* like copy_bytes_(), but free()s the original '*to' if the copy succeeds and the original '*to' is non-NULL */
  71. static FLAC__bool free_copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
  72. {
  73. FLAC__byte *copy;
  74. FLAC__ASSERT(0 != to);
  75. if(copy_bytes_(&copy, from, bytes)) {
  76. if(*to)
  77. free(*to);
  78. *to = copy;
  79. return true;
  80. }
  81. else
  82. return false;
  83. }
  84. #endif
  85. /* reallocate entry to 1 byte larger and add a terminating NUL */
  86. /* realloc() failure leaves entry unchanged */
  87. static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, unsigned length)
  88. {
  89. FLAC__byte *x = (FLAC__byte*)safe_realloc_add_2op_(*entry, length, /*+*/1);
  90. if(0 != x) {
  91. x[length] = '\0';
  92. *entry = x;
  93. return true;
  94. }
  95. else
  96. return false;
  97. }
  98. /* copies the NUL-terminated C-string 'from' to '*to', leaving '*to'
  99. * unchanged if malloc fails, free()ing the original '*to' if it
  100. * succeeds and the original '*to' was not NULL
  101. */
  102. static FLAC__bool copy_cstring_(char **to, const char *from)
  103. {
  104. char *copy = strdup(from);
  105. FLAC__ASSERT(to);
  106. if(copy) {
  107. if(*to)
  108. free(*to);
  109. *to = copy;
  110. return true;
  111. }
  112. else
  113. return false;
  114. }
  115. static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, const FLAC__StreamMetadata_VorbisComment_Entry *from)
  116. {
  117. to->length = from->length;
  118. if(0 == from->entry) {
  119. FLAC__ASSERT(from->length == 0);
  120. to->entry = 0;
  121. }
  122. else {
  123. FLAC__byte *x;
  124. FLAC__ASSERT(from->length > 0);
  125. if(0 == (x = (FLAC__byte*)safe_malloc_add_2op_(from->length, /*+*/1)))
  126. return false;
  127. memcpy(x, from->entry, from->length);
  128. x[from->length] = '\0';
  129. to->entry = x;
  130. }
  131. return true;
  132. }
  133. static FLAC__bool copy_track_(FLAC__StreamMetadata_CueSheet_Track *to, const FLAC__StreamMetadata_CueSheet_Track *from)
  134. {
  135. memcpy(to, from, sizeof(FLAC__StreamMetadata_CueSheet_Track));
  136. if(0 == from->indices) {
  137. FLAC__ASSERT(from->num_indices == 0);
  138. }
  139. else {
  140. FLAC__StreamMetadata_CueSheet_Index *x;
  141. FLAC__ASSERT(from->num_indices > 0);
  142. if(0 == (x = (FLAC__StreamMetadata_CueSheet_Index*)safe_malloc_mul_2op_(from->num_indices, /*times*/sizeof(FLAC__StreamMetadata_CueSheet_Index))))
  143. return false;
  144. memcpy(x, from->indices, from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
  145. to->indices = x;
  146. }
  147. return true;
  148. }
  149. static void seektable_calculate_length_(FLAC__StreamMetadata *object)
  150. {
  151. FLAC__ASSERT(0 != object);
  152. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  153. object->length = object->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
  154. }
  155. static FLAC__StreamMetadata_SeekPoint *seekpoint_array_new_(unsigned num_points)
  156. {
  157. FLAC__StreamMetadata_SeekPoint *object_array;
  158. FLAC__ASSERT(num_points > 0);
  159. object_array = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint));
  160. if(0 != object_array) {
  161. unsigned i;
  162. for(i = 0; i < num_points; i++) {
  163. object_array[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
  164. object_array[i].stream_offset = 0;
  165. object_array[i].frame_samples = 0;
  166. }
  167. }
  168. return object_array;
  169. }
  170. static void vorbiscomment_calculate_length_(FLAC__StreamMetadata *object)
  171. {
  172. unsigned i;
  173. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  174. object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN) / 8;
  175. object->length += object->data.vorbis_comment.vendor_string.length;
  176. object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8;
  177. for(i = 0; i < object->data.vorbis_comment.num_comments; i++) {
  178. object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8);
  179. object->length += object->data.vorbis_comment.comments[i].length;
  180. }
  181. }
  182. static FLAC__StreamMetadata_VorbisComment_Entry *vorbiscomment_entry_array_new_(unsigned num_comments)
  183. {
  184. FLAC__ASSERT(num_comments > 0);
  185. return (FLAC__StreamMetadata_VorbisComment_Entry*)safe_calloc_(num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
  186. }
  187. static void vorbiscomment_entry_array_delete_(FLAC__StreamMetadata_VorbisComment_Entry *object_array, unsigned num_comments)
  188. {
  189. unsigned i;
  190. FLAC__ASSERT(0 != object_array && num_comments > 0);
  191. for(i = 0; i < num_comments; i++)
  192. if(0 != object_array[i].entry)
  193. free(object_array[i].entry);
  194. if(0 != object_array)
  195. free(object_array);
  196. }
  197. static FLAC__StreamMetadata_VorbisComment_Entry *vorbiscomment_entry_array_copy_(const FLAC__StreamMetadata_VorbisComment_Entry *object_array, unsigned num_comments)
  198. {
  199. FLAC__StreamMetadata_VorbisComment_Entry *return_array;
  200. FLAC__ASSERT(0 != object_array);
  201. FLAC__ASSERT(num_comments > 0);
  202. return_array = vorbiscomment_entry_array_new_(num_comments);
  203. if(0 != return_array) {
  204. unsigned i;
  205. for(i = 0; i < num_comments; i++) {
  206. if(!copy_vcentry_(return_array+i, object_array+i)) {
  207. vorbiscomment_entry_array_delete_(return_array, num_comments);
  208. return 0;
  209. }
  210. }
  211. }
  212. return return_array;
  213. }
  214. static FLAC__bool vorbiscomment_set_entry_(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry *dest, const FLAC__StreamMetadata_VorbisComment_Entry *src, FLAC__bool copy)
  215. {
  216. FLAC__byte *save;
  217. FLAC__ASSERT(0 != object);
  218. FLAC__ASSERT(0 != dest);
  219. FLAC__ASSERT(0 != src);
  220. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  221. FLAC__ASSERT((0 != src->entry && src->length > 0) || (0 == src->entry && src->length == 0));
  222. save = dest->entry;
  223. if(0 != src->entry && src->length > 0) {
  224. if(copy) {
  225. /* do the copy first so that if we fail we leave the dest object untouched */
  226. if(!copy_vcentry_(dest, src))
  227. return false;
  228. }
  229. else {
  230. /* we have to make sure that the string we're taking over is null-terminated */
  231. /*
  232. * Stripping the const from src->entry is OK since we're taking
  233. * ownership of the pointer. This is a hack around a deficiency
  234. * in the API where the same function is used for 'copy' and
  235. * 'own', but the source entry is a const pointer. If we were
  236. * precise, the 'own' flavor would be a separate function with a
  237. * non-const source pointer. But it's not, so we hack away.
  238. */
  239. if(!ensure_null_terminated_((FLAC__byte**)(&src->entry), src->length))
  240. return false;
  241. *dest = *src;
  242. }
  243. }
  244. else {
  245. /* the src is null */
  246. *dest = *src;
  247. }
  248. if(0 != save)
  249. free(save);
  250. vorbiscomment_calculate_length_(object);
  251. return true;
  252. }
  253. static int vorbiscomment_find_entry_from_(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name, unsigned field_name_length)
  254. {
  255. unsigned i;
  256. FLAC__ASSERT(0 != object);
  257. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  258. FLAC__ASSERT(0 != field_name);
  259. for(i = offset; i < object->data.vorbis_comment.num_comments; i++) {
  260. if(FLAC__metadata_object_vorbiscomment_entry_matches(object->data.vorbis_comment.comments[i], field_name, field_name_length))
  261. return (int)i;
  262. }
  263. return -1;
  264. }
  265. static void cuesheet_calculate_length_(FLAC__StreamMetadata *object)
  266. {
  267. unsigned i;
  268. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  269. object->length = (
  270. FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
  271. FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
  272. FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN +
  273. FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN +
  274. FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
  275. ) / 8;
  276. object->length += object->data.cue_sheet.num_tracks * (
  277. FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
  278. FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
  279. FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
  280. FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
  281. FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
  282. FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
  283. FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
  284. ) / 8;
  285. for(i = 0; i < object->data.cue_sheet.num_tracks; i++) {
  286. object->length += object->data.cue_sheet.tracks[i].num_indices * (
  287. FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
  288. FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
  289. FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
  290. ) / 8;
  291. }
  292. }
  293. static FLAC__StreamMetadata_CueSheet_Index *cuesheet_track_index_array_new_(unsigned num_indices)
  294. {
  295. FLAC__ASSERT(num_indices > 0);
  296. return (FLAC__StreamMetadata_CueSheet_Index*)safe_calloc_(num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index));
  297. }
  298. static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_new_(unsigned num_tracks)
  299. {
  300. FLAC__ASSERT(num_tracks > 0);
  301. return (FLAC__StreamMetadata_CueSheet_Track*)safe_calloc_(num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
  302. }
  303. static void cuesheet_track_array_delete_(FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks)
  304. {
  305. unsigned i;
  306. FLAC__ASSERT(0 != object_array && num_tracks > 0);
  307. for(i = 0; i < num_tracks; i++) {
  308. if(0 != object_array[i].indices) {
  309. FLAC__ASSERT(object_array[i].num_indices > 0);
  310. free(object_array[i].indices);
  311. }
  312. }
  313. if(0 != object_array)
  314. free(object_array);
  315. }
  316. static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_copy_(const FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks)
  317. {
  318. FLAC__StreamMetadata_CueSheet_Track *return_array;
  319. FLAC__ASSERT(0 != object_array);
  320. FLAC__ASSERT(num_tracks > 0);
  321. return_array = cuesheet_track_array_new_(num_tracks);
  322. if(0 != return_array) {
  323. unsigned i;
  324. for(i = 0; i < num_tracks; i++) {
  325. if(!copy_track_(return_array+i, object_array+i)) {
  326. cuesheet_track_array_delete_(return_array, num_tracks);
  327. return 0;
  328. }
  329. }
  330. }
  331. return return_array;
  332. }
  333. static FLAC__bool cuesheet_set_track_(FLAC__StreamMetadata *object, FLAC__StreamMetadata_CueSheet_Track *dest, const FLAC__StreamMetadata_CueSheet_Track *src, FLAC__bool copy)
  334. {
  335. FLAC__StreamMetadata_CueSheet_Index *save;
  336. FLAC__ASSERT(0 != object);
  337. FLAC__ASSERT(0 != dest);
  338. FLAC__ASSERT(0 != src);
  339. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  340. FLAC__ASSERT((0 != src->indices && src->num_indices > 0) || (0 == src->indices && src->num_indices == 0));
  341. save = dest->indices;
  342. /* do the copy first so that if we fail we leave the object untouched */
  343. if(copy) {
  344. if(!copy_track_(dest, src))
  345. return false;
  346. }
  347. else {
  348. *dest = *src;
  349. }
  350. if(0 != save)
  351. free(save);
  352. cuesheet_calculate_length_(object);
  353. return true;
  354. }
  355. /****************************************************************************
  356. *
  357. * Metadata object routines
  358. *
  359. ***************************************************************************/
  360. FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type)
  361. {
  362. FLAC__StreamMetadata *object;
  363. if(type > FLAC__MAX_METADATA_TYPE_CODE)
  364. return 0;
  365. object = (FLAC__StreamMetadata*)calloc(1, sizeof(FLAC__StreamMetadata));
  366. if(0 != object) {
  367. object->is_last = false;
  368. object->type = type;
  369. switch(type) {
  370. case FLAC__METADATA_TYPE_STREAMINFO:
  371. object->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
  372. break;
  373. case FLAC__METADATA_TYPE_PADDING:
  374. /* calloc() took care of this for us:
  375. object->length = 0;
  376. */
  377. break;
  378. case FLAC__METADATA_TYPE_APPLICATION:
  379. object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
  380. /* calloc() took care of this for us:
  381. object->data.application.data = 0;
  382. */
  383. break;
  384. case FLAC__METADATA_TYPE_SEEKTABLE:
  385. /* calloc() took care of this for us:
  386. object->length = 0;
  387. object->data.seek_table.num_points = 0;
  388. object->data.seek_table.points = 0;
  389. */
  390. break;
  391. case FLAC__METADATA_TYPE_VORBIS_COMMENT:
  392. object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING);
  393. if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) {
  394. free(object);
  395. return 0;
  396. }
  397. vorbiscomment_calculate_length_(object);
  398. break;
  399. case FLAC__METADATA_TYPE_CUESHEET:
  400. cuesheet_calculate_length_(object);
  401. break;
  402. case FLAC__METADATA_TYPE_PICTURE:
  403. object->length = (
  404. FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
  405. FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* empty mime_type string */
  406. FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* empty description string */
  407. FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
  408. FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
  409. FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
  410. FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
  411. FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN +
  412. 0 /* no data */
  413. ) / 8;
  414. object->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER;
  415. object->data.picture.mime_type = 0;
  416. object->data.picture.description = 0;
  417. /* calloc() took care of this for us:
  418. object->data.picture.width = 0;
  419. object->data.picture.height = 0;
  420. object->data.picture.depth = 0;
  421. object->data.picture.colors = 0;
  422. object->data.picture.data_length = 0;
  423. object->data.picture.data = 0;
  424. */
  425. /* now initialize mime_type and description with empty strings to make things easier on the client */
  426. if(!copy_cstring_(&object->data.picture.mime_type, "")) {
  427. free(object);
  428. return 0;
  429. }
  430. if(!copy_cstring_((char**)(&object->data.picture.description), "")) {
  431. if(object->data.picture.mime_type)
  432. free(object->data.picture.mime_type);
  433. free(object);
  434. return 0;
  435. }
  436. break;
  437. default:
  438. /* calloc() took care of this for us:
  439. object->length = 0;
  440. object->data.unknown.data = 0;
  441. */
  442. break;
  443. }
  444. }
  445. return object;
  446. }
  447. FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_clone(const FLAC__StreamMetadata *object)
  448. {
  449. FLAC__StreamMetadata *to;
  450. FLAC__ASSERT(0 != object);
  451. if(0 != (to = FLAC__metadata_object_new(object->type))) {
  452. to->is_last = object->is_last;
  453. to->type = object->type;
  454. to->length = object->length;
  455. switch(to->type) {
  456. case FLAC__METADATA_TYPE_STREAMINFO:
  457. memcpy(&to->data.stream_info, &object->data.stream_info, sizeof(FLAC__StreamMetadata_StreamInfo));
  458. break;
  459. case FLAC__METADATA_TYPE_PADDING:
  460. break;
  461. case FLAC__METADATA_TYPE_APPLICATION:
  462. if(to->length < FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8) { /* underflow check */
  463. FLAC__metadata_object_delete(to);
  464. return 0;
  465. }
  466. memcpy(&to->data.application.id, &object->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8);
  467. if(!copy_bytes_(&to->data.application.data, object->data.application.data, object->length - FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) {
  468. FLAC__metadata_object_delete(to);
  469. return 0;
  470. }
  471. break;
  472. case FLAC__METADATA_TYPE_SEEKTABLE:
  473. to->data.seek_table.num_points = object->data.seek_table.num_points;
  474. if(to->data.seek_table.num_points > SIZE_MAX / sizeof(FLAC__StreamMetadata_SeekPoint)) { /* overflow check */
  475. FLAC__metadata_object_delete(to);
  476. return 0;
  477. }
  478. if(!copy_bytes_((FLAC__byte**)&to->data.seek_table.points, (FLAC__byte*)object->data.seek_table.points, object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint))) {
  479. FLAC__metadata_object_delete(to);
  480. return 0;
  481. }
  482. break;
  483. case FLAC__METADATA_TYPE_VORBIS_COMMENT:
  484. if(0 != to->data.vorbis_comment.vendor_string.entry) {
  485. free(to->data.vorbis_comment.vendor_string.entry);
  486. to->data.vorbis_comment.vendor_string.entry = 0;
  487. }
  488. if(!copy_vcentry_(&to->data.vorbis_comment.vendor_string, &object->data.vorbis_comment.vendor_string)) {
  489. FLAC__metadata_object_delete(to);
  490. return 0;
  491. }
  492. if(object->data.vorbis_comment.num_comments == 0) {
  493. FLAC__ASSERT(0 == object->data.vorbis_comment.comments);
  494. to->data.vorbis_comment.comments = 0;
  495. }
  496. else {
  497. FLAC__ASSERT(0 != object->data.vorbis_comment.comments);
  498. to->data.vorbis_comment.comments = vorbiscomment_entry_array_copy_(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments);
  499. if(0 == to->data.vorbis_comment.comments) {
  500. FLAC__metadata_object_delete(to);
  501. return 0;
  502. }
  503. }
  504. to->data.vorbis_comment.num_comments = object->data.vorbis_comment.num_comments;
  505. break;
  506. case FLAC__METADATA_TYPE_CUESHEET:
  507. memcpy(&to->data.cue_sheet, &object->data.cue_sheet, sizeof(FLAC__StreamMetadata_CueSheet));
  508. if(object->data.cue_sheet.num_tracks == 0) {
  509. FLAC__ASSERT(0 == object->data.cue_sheet.tracks);
  510. }
  511. else {
  512. FLAC__ASSERT(0 != object->data.cue_sheet.tracks);
  513. to->data.cue_sheet.tracks = cuesheet_track_array_copy_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
  514. if(0 == to->data.cue_sheet.tracks) {
  515. FLAC__metadata_object_delete(to);
  516. return 0;
  517. }
  518. }
  519. break;
  520. case FLAC__METADATA_TYPE_PICTURE:
  521. to->data.picture.type = object->data.picture.type;
  522. if(!copy_cstring_(&to->data.picture.mime_type, object->data.picture.mime_type)) {
  523. FLAC__metadata_object_delete(to);
  524. return 0;
  525. }
  526. if(!copy_cstring_((char**)(&to->data.picture.description), (const char*)object->data.picture.description)) {
  527. FLAC__metadata_object_delete(to);
  528. return 0;
  529. }
  530. to->data.picture.width = object->data.picture.width;
  531. to->data.picture.height = object->data.picture.height;
  532. to->data.picture.depth = object->data.picture.depth;
  533. to->data.picture.colors = object->data.picture.colors;
  534. to->data.picture.data_length = object->data.picture.data_length;
  535. if(!copy_bytes_((&to->data.picture.data), object->data.picture.data, object->data.picture.data_length)) {
  536. FLAC__metadata_object_delete(to);
  537. return 0;
  538. }
  539. break;
  540. default:
  541. if(!copy_bytes_(&to->data.unknown.data, object->data.unknown.data, object->length)) {
  542. FLAC__metadata_object_delete(to);
  543. return 0;
  544. }
  545. break;
  546. }
  547. }
  548. return to;
  549. }
  550. void FLAC__metadata_object_delete_data(FLAC__StreamMetadata *object)
  551. {
  552. FLAC__ASSERT(0 != object);
  553. switch(object->type) {
  554. case FLAC__METADATA_TYPE_STREAMINFO:
  555. case FLAC__METADATA_TYPE_PADDING:
  556. break;
  557. case FLAC__METADATA_TYPE_APPLICATION:
  558. if(0 != object->data.application.data) {
  559. free(object->data.application.data);
  560. object->data.application.data = 0;
  561. }
  562. break;
  563. case FLAC__METADATA_TYPE_SEEKTABLE:
  564. if(0 != object->data.seek_table.points) {
  565. free(object->data.seek_table.points);
  566. object->data.seek_table.points = 0;
  567. }
  568. break;
  569. case FLAC__METADATA_TYPE_VORBIS_COMMENT:
  570. if(0 != object->data.vorbis_comment.vendor_string.entry) {
  571. free(object->data.vorbis_comment.vendor_string.entry);
  572. object->data.vorbis_comment.vendor_string.entry = 0;
  573. }
  574. if(0 != object->data.vorbis_comment.comments) {
  575. FLAC__ASSERT(object->data.vorbis_comment.num_comments > 0);
  576. vorbiscomment_entry_array_delete_(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments);
  577. }
  578. break;
  579. case FLAC__METADATA_TYPE_CUESHEET:
  580. if(0 != object->data.cue_sheet.tracks) {
  581. FLAC__ASSERT(object->data.cue_sheet.num_tracks > 0);
  582. cuesheet_track_array_delete_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
  583. }
  584. break;
  585. case FLAC__METADATA_TYPE_PICTURE:
  586. if(0 != object->data.picture.mime_type) {
  587. free(object->data.picture.mime_type);
  588. object->data.picture.mime_type = 0;
  589. }
  590. if(0 != object->data.picture.description) {
  591. free(object->data.picture.description);
  592. object->data.picture.description = 0;
  593. }
  594. if(0 != object->data.picture.data) {
  595. free(object->data.picture.data);
  596. object->data.picture.data = 0;
  597. }
  598. break;
  599. default:
  600. if(0 != object->data.unknown.data) {
  601. free(object->data.unknown.data);
  602. object->data.unknown.data = 0;
  603. }
  604. break;
  605. }
  606. }
  607. FLAC_API void FLAC__metadata_object_delete(FLAC__StreamMetadata *object)
  608. {
  609. FLAC__metadata_object_delete_data(object);
  610. free(object);
  611. }
  612. static FLAC__bool compare_block_data_streaminfo_(const FLAC__StreamMetadata_StreamInfo *block1, const FLAC__StreamMetadata_StreamInfo *block2)
  613. {
  614. if(block1->min_blocksize != block2->min_blocksize)
  615. return false;
  616. if(block1->max_blocksize != block2->max_blocksize)
  617. return false;
  618. if(block1->min_framesize != block2->min_framesize)
  619. return false;
  620. if(block1->max_framesize != block2->max_framesize)
  621. return false;
  622. if(block1->sample_rate != block2->sample_rate)
  623. return false;
  624. if(block1->channels != block2->channels)
  625. return false;
  626. if(block1->bits_per_sample != block2->bits_per_sample)
  627. return false;
  628. if(block1->total_samples != block2->total_samples)
  629. return false;
  630. if(0 != memcmp(block1->md5sum, block2->md5sum, 16))
  631. return false;
  632. return true;
  633. }
  634. static FLAC__bool compare_block_data_application_(const FLAC__StreamMetadata_Application *block1, const FLAC__StreamMetadata_Application *block2, unsigned block_length)
  635. {
  636. FLAC__ASSERT(0 != block1);
  637. FLAC__ASSERT(0 != block2);
  638. FLAC__ASSERT(block_length >= sizeof(block1->id));
  639. if(0 != memcmp(block1->id, block2->id, sizeof(block1->id)))
  640. return false;
  641. if(0 != block1->data && 0 != block2->data)
  642. return 0 == memcmp(block1->data, block2->data, block_length - sizeof(block1->id));
  643. else
  644. return block1->data == block2->data;
  645. }
  646. static FLAC__bool compare_block_data_seektable_(const FLAC__StreamMetadata_SeekTable *block1, const FLAC__StreamMetadata_SeekTable *block2)
  647. {
  648. unsigned i;
  649. FLAC__ASSERT(0 != block1);
  650. FLAC__ASSERT(0 != block2);
  651. if(block1->num_points != block2->num_points)
  652. return false;
  653. if(0 != block1->points && 0 != block2->points) {
  654. for(i = 0; i < block1->num_points; i++) {
  655. if(block1->points[i].sample_number != block2->points[i].sample_number)
  656. return false;
  657. if(block1->points[i].stream_offset != block2->points[i].stream_offset)
  658. return false;
  659. if(block1->points[i].frame_samples != block2->points[i].frame_samples)
  660. return false;
  661. }
  662. return true;
  663. }
  664. else
  665. return block1->points == block2->points;
  666. }
  667. static FLAC__bool compare_block_data_vorbiscomment_(const FLAC__StreamMetadata_VorbisComment *block1, const FLAC__StreamMetadata_VorbisComment *block2)
  668. {
  669. unsigned i;
  670. if(block1->vendor_string.length != block2->vendor_string.length)
  671. return false;
  672. if(0 != block1->vendor_string.entry && 0 != block2->vendor_string.entry) {
  673. if(0 != memcmp(block1->vendor_string.entry, block2->vendor_string.entry, block1->vendor_string.length))
  674. return false;
  675. }
  676. else if(block1->vendor_string.entry != block2->vendor_string.entry)
  677. return false;
  678. if(block1->num_comments != block2->num_comments)
  679. return false;
  680. for(i = 0; i < block1->num_comments; i++) {
  681. if(0 != block1->comments[i].entry && 0 != block2->comments[i].entry) {
  682. if(0 != memcmp(block1->comments[i].entry, block2->comments[i].entry, block1->comments[i].length))
  683. return false;
  684. }
  685. else if(block1->comments[i].entry != block2->comments[i].entry)
  686. return false;
  687. }
  688. return true;
  689. }
  690. static FLAC__bool compare_block_data_cuesheet_(const FLAC__StreamMetadata_CueSheet *block1, const FLAC__StreamMetadata_CueSheet *block2)
  691. {
  692. unsigned i, j;
  693. if(0 != strcmp(block1->media_catalog_number, block2->media_catalog_number))
  694. return false;
  695. if(block1->lead_in != block2->lead_in)
  696. return false;
  697. if(block1->is_cd != block2->is_cd)
  698. return false;
  699. if(block1->num_tracks != block2->num_tracks)
  700. return false;
  701. if(0 != block1->tracks && 0 != block2->tracks) {
  702. FLAC__ASSERT(block1->num_tracks > 0);
  703. for(i = 0; i < block1->num_tracks; i++) {
  704. if(block1->tracks[i].offset != block2->tracks[i].offset)
  705. return false;
  706. if(block1->tracks[i].number != block2->tracks[i].number)
  707. return false;
  708. if(0 != memcmp(block1->tracks[i].isrc, block2->tracks[i].isrc, sizeof(block1->tracks[i].isrc)))
  709. return false;
  710. if(block1->tracks[i].type != block2->tracks[i].type)
  711. return false;
  712. if(block1->tracks[i].pre_emphasis != block2->tracks[i].pre_emphasis)
  713. return false;
  714. if(block1->tracks[i].num_indices != block2->tracks[i].num_indices)
  715. return false;
  716. if(0 != block1->tracks[i].indices && 0 != block2->tracks[i].indices) {
  717. FLAC__ASSERT(block1->tracks[i].num_indices > 0);
  718. for(j = 0; j < block1->tracks[i].num_indices; j++) {
  719. if(block1->tracks[i].indices[j].offset != block2->tracks[i].indices[j].offset)
  720. return false;
  721. if(block1->tracks[i].indices[j].number != block2->tracks[i].indices[j].number)
  722. return false;
  723. }
  724. }
  725. else if(block1->tracks[i].indices != block2->tracks[i].indices)
  726. return false;
  727. }
  728. }
  729. else if(block1->tracks != block2->tracks)
  730. return false;
  731. return true;
  732. }
  733. static FLAC__bool compare_block_data_picture_(const FLAC__StreamMetadata_Picture *block1, const FLAC__StreamMetadata_Picture *block2)
  734. {
  735. if(block1->type != block2->type)
  736. return false;
  737. if(block1->mime_type != block2->mime_type && (0 == block1->mime_type || 0 == block2->mime_type || strcmp(block1->mime_type, block2->mime_type)))
  738. return false;
  739. if(block1->description != block2->description && (0 == block1->description || 0 == block2->description || strcmp((const char *)block1->description, (const char *)block2->description)))
  740. return false;
  741. if(block1->width != block2->width)
  742. return false;
  743. if(block1->height != block2->height)
  744. return false;
  745. if(block1->depth != block2->depth)
  746. return false;
  747. if(block1->colors != block2->colors)
  748. return false;
  749. if(block1->data_length != block2->data_length)
  750. return false;
  751. if(block1->data != block2->data && (0 == block1->data || 0 == block2->data || memcmp(block1->data, block2->data, block1->data_length)))
  752. return false;
  753. return true;
  754. }
  755. static FLAC__bool compare_block_data_unknown_(const FLAC__StreamMetadata_Unknown *block1, const FLAC__StreamMetadata_Unknown *block2, unsigned block_length)
  756. {
  757. FLAC__ASSERT(0 != block1);
  758. FLAC__ASSERT(0 != block2);
  759. if(0 != block1->data && 0 != block2->data)
  760. return 0 == memcmp(block1->data, block2->data, block_length);
  761. else
  762. return block1->data == block2->data;
  763. }
  764. FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *block1, const FLAC__StreamMetadata *block2)
  765. {
  766. FLAC__ASSERT(0 != block1);
  767. FLAC__ASSERT(0 != block2);
  768. if(block1->type != block2->type) {
  769. return false;
  770. }
  771. if(block1->is_last != block2->is_last) {
  772. return false;
  773. }
  774. if(block1->length != block2->length) {
  775. return false;
  776. }
  777. switch(block1->type) {
  778. case FLAC__METADATA_TYPE_STREAMINFO:
  779. return compare_block_data_streaminfo_(&block1->data.stream_info, &block2->data.stream_info);
  780. case FLAC__METADATA_TYPE_PADDING:
  781. return true; /* we don't compare the padding guts */
  782. case FLAC__METADATA_TYPE_APPLICATION:
  783. return compare_block_data_application_(&block1->data.application, &block2->data.application, block1->length);
  784. case FLAC__METADATA_TYPE_SEEKTABLE:
  785. return compare_block_data_seektable_(&block1->data.seek_table, &block2->data.seek_table);
  786. case FLAC__METADATA_TYPE_VORBIS_COMMENT:
  787. return compare_block_data_vorbiscomment_(&block1->data.vorbis_comment, &block2->data.vorbis_comment);
  788. case FLAC__METADATA_TYPE_CUESHEET:
  789. return compare_block_data_cuesheet_(&block1->data.cue_sheet, &block2->data.cue_sheet);
  790. case FLAC__METADATA_TYPE_PICTURE:
  791. return compare_block_data_picture_(&block1->data.picture, &block2->data.picture);
  792. default:
  793. return compare_block_data_unknown_(&block1->data.unknown, &block2->data.unknown, block1->length);
  794. }
  795. }
  796. FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, unsigned length, FLAC__bool copy)
  797. {
  798. FLAC__byte *save;
  799. FLAC__ASSERT(0 != object);
  800. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_APPLICATION);
  801. FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
  802. save = object->data.application.data;
  803. /* do the copy first so that if we fail we leave the object untouched */
  804. if(copy) {
  805. if(!copy_bytes_(&object->data.application.data, data, length))
  806. return false;
  807. }
  808. else {
  809. object->data.application.data = data;
  810. }
  811. if(0 != save)
  812. free(save);
  813. object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8 + length;
  814. return true;
  815. }
  816. FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, unsigned new_num_points)
  817. {
  818. FLAC__ASSERT(0 != object);
  819. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  820. if(0 == object->data.seek_table.points) {
  821. FLAC__ASSERT(object->data.seek_table.num_points == 0);
  822. if(0 == new_num_points)
  823. return true;
  824. else if(0 == (object->data.seek_table.points = seekpoint_array_new_(new_num_points)))
  825. return false;
  826. }
  827. else {
  828. const size_t old_size = object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint);
  829. const size_t new_size = new_num_points * sizeof(FLAC__StreamMetadata_SeekPoint);
  830. /* overflow check */
  831. if((size_t)new_num_points > SIZE_MAX / sizeof(FLAC__StreamMetadata_SeekPoint))
  832. return false;
  833. FLAC__ASSERT(object->data.seek_table.num_points > 0);
  834. if(new_size == 0) {
  835. free(object->data.seek_table.points);
  836. object->data.seek_table.points = 0;
  837. }
  838. else if(0 == (object->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)realloc(object->data.seek_table.points, new_size)))
  839. return false;
  840. /* if growing, set new elements to placeholders */
  841. if(new_size > old_size) {
  842. unsigned i;
  843. for(i = object->data.seek_table.num_points; i < new_num_points; i++) {
  844. object->data.seek_table.points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
  845. object->data.seek_table.points[i].stream_offset = 0;
  846. object->data.seek_table.points[i].frame_samples = 0;
  847. }
  848. }
  849. }
  850. object->data.seek_table.num_points = new_num_points;
  851. seektable_calculate_length_(object);
  852. return true;
  853. }
  854. FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point)
  855. {
  856. FLAC__ASSERT(0 != object);
  857. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  858. FLAC__ASSERT(point_num < object->data.seek_table.num_points);
  859. object->data.seek_table.points[point_num] = point;
  860. }
  861. FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point)
  862. {
  863. int i;
  864. FLAC__ASSERT(0 != object);
  865. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  866. FLAC__ASSERT(point_num <= object->data.seek_table.num_points);
  867. if(!FLAC__metadata_object_seektable_resize_points(object, object->data.seek_table.num_points+1))
  868. return false;
  869. /* move all points >= point_num forward one space */
  870. for(i = (int)object->data.seek_table.num_points-1; i > (int)point_num; i--)
  871. object->data.seek_table.points[i] = object->data.seek_table.points[i-1];
  872. FLAC__metadata_object_seektable_set_point(object, point_num, point);
  873. seektable_calculate_length_(object);
  874. return true;
  875. }
  876. FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, unsigned point_num)
  877. {
  878. unsigned i;
  879. FLAC__ASSERT(0 != object);
  880. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  881. FLAC__ASSERT(point_num < object->data.seek_table.num_points);
  882. /* move all points > point_num backward one space */
  883. for(i = point_num; i < object->data.seek_table.num_points-1; i++)
  884. object->data.seek_table.points[i] = object->data.seek_table.points[i+1];
  885. return FLAC__metadata_object_seektable_resize_points(object, object->data.seek_table.num_points-1);
  886. }
  887. FLAC_API FLAC__bool FLAC__metadata_object_seektable_is_legal(const FLAC__StreamMetadata *object)
  888. {
  889. FLAC__ASSERT(0 != object);
  890. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  891. return FLAC__format_seektable_is_legal(&object->data.seek_table);
  892. }
  893. FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, unsigned num)
  894. {
  895. FLAC__ASSERT(0 != object);
  896. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  897. if(num > 0)
  898. /* WATCHOUT: we rely on the fact that growing the array adds PLACEHOLDERS at the end */
  899. return FLAC__metadata_object_seektable_resize_points(object, object->data.seek_table.num_points + num);
  900. else
  901. return true;
  902. }
  903. FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_point(FLAC__StreamMetadata *object, FLAC__uint64 sample_number)
  904. {
  905. FLAC__StreamMetadata_SeekTable *seek_table;
  906. FLAC__ASSERT(0 != object);
  907. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  908. seek_table = &object->data.seek_table;
  909. if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + 1))
  910. return false;
  911. seek_table->points[seek_table->num_points - 1].sample_number = sample_number;
  912. seek_table->points[seek_table->num_points - 1].stream_offset = 0;
  913. seek_table->points[seek_table->num_points - 1].frame_samples = 0;
  914. return true;
  915. }
  916. FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], unsigned num)
  917. {
  918. FLAC__ASSERT(0 != object);
  919. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  920. FLAC__ASSERT(0 != sample_numbers || num == 0);
  921. if(num > 0) {
  922. FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table;
  923. unsigned i, j;
  924. i = seek_table->num_points;
  925. if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + num))
  926. return false;
  927. for(j = 0; j < num; i++, j++) {
  928. seek_table->points[i].sample_number = sample_numbers[j];
  929. seek_table->points[i].stream_offset = 0;
  930. seek_table->points[i].frame_samples = 0;
  931. }
  932. }
  933. return true;
  934. }
  935. FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples)
  936. {
  937. FLAC__ASSERT(0 != object);
  938. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  939. FLAC__ASSERT(total_samples > 0);
  940. if(num > 0 && total_samples > 0) {
  941. FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table;
  942. unsigned i, j;
  943. i = seek_table->num_points;
  944. if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + num))
  945. return false;
  946. for(j = 0; j < num; i++, j++) {
  947. seek_table->points[i].sample_number = total_samples * (FLAC__uint64)j / (FLAC__uint64)num;
  948. seek_table->points[i].stream_offset = 0;
  949. seek_table->points[i].frame_samples = 0;
  950. }
  951. }
  952. return true;
  953. }
  954. FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples)
  955. {
  956. FLAC__ASSERT(0 != object);
  957. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  958. FLAC__ASSERT(samples > 0);
  959. FLAC__ASSERT(total_samples > 0);
  960. if(samples > 0 && total_samples > 0) {
  961. FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table;
  962. unsigned i, j;
  963. FLAC__uint64 num, sample;
  964. num = 1 + total_samples / samples; /* 1+ for the first sample at 0 */
  965. /* now account for the fact that we don't place a seekpoint at "total_samples" since samples are number from 0: */
  966. if(total_samples % samples == 0)
  967. num--;
  968. i = seek_table->num_points;
  969. if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + (unsigned)num))
  970. return false;
  971. sample = 0;
  972. for(j = 0; j < num; i++, j++, sample += samples) {
  973. seek_table->points[i].sample_number = sample;
  974. seek_table->points[i].stream_offset = 0;
  975. seek_table->points[i].frame_samples = 0;
  976. }
  977. }
  978. return true;
  979. }
  980. FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata *object, FLAC__bool compact)
  981. {
  982. unsigned unique;
  983. FLAC__ASSERT(0 != object);
  984. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
  985. unique = FLAC__format_seektable_sort(&object->data.seek_table);
  986. return !compact || FLAC__metadata_object_seektable_resize_points(object, unique);
  987. }
  988. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy)
  989. {
  990. if(!FLAC__format_vorbiscomment_entry_value_is_legal(entry.entry, entry.length))
  991. return false;
  992. return vorbiscomment_set_entry_(object, &object->data.vorbis_comment.vendor_string, &entry, copy);
  993. }
  994. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, unsigned new_num_comments)
  995. {
  996. FLAC__ASSERT(0 != object);
  997. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  998. if(0 == object->data.vorbis_comment.comments) {
  999. FLAC__ASSERT(object->data.vorbis_comment.num_comments == 0);
  1000. if(0 == new_num_comments)
  1001. return true;
  1002. else if(0 == (object->data.vorbis_comment.comments = vorbiscomment_entry_array_new_(new_num_comments)))
  1003. return false;
  1004. }
  1005. else {
  1006. const size_t old_size = object->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry);
  1007. const size_t new_size = new_num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry);
  1008. /* overflow check */
  1009. if((size_t)new_num_comments > SIZE_MAX / sizeof(FLAC__StreamMetadata_VorbisComment_Entry))
  1010. return false;
  1011. FLAC__ASSERT(object->data.vorbis_comment.num_comments > 0);
  1012. /* if shrinking, free the truncated entries */
  1013. if(new_num_comments < object->data.vorbis_comment.num_comments) {
  1014. unsigned i;
  1015. for(i = new_num_comments; i < object->data.vorbis_comment.num_comments; i++)
  1016. if(0 != object->data.vorbis_comment.comments[i].entry)
  1017. free(object->data.vorbis_comment.comments[i].entry);
  1018. }
  1019. if(new_size == 0) {
  1020. free(object->data.vorbis_comment.comments);
  1021. object->data.vorbis_comment.comments = 0;
  1022. }
  1023. else if(0 == (object->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)realloc(object->data.vorbis_comment.comments, new_size)))
  1024. return false;
  1025. /* if growing, zero all the length/pointers of new elements */
  1026. if(new_size > old_size)
  1027. memset(object->data.vorbis_comment.comments + object->data.vorbis_comment.num_comments, 0, new_size - old_size);
  1028. }
  1029. object->data.vorbis_comment.num_comments = new_num_comments;
  1030. vorbiscomment_calculate_length_(object);
  1031. return true;
  1032. }
  1033. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy)
  1034. {
  1035. FLAC__ASSERT(0 != object);
  1036. FLAC__ASSERT(comment_num < object->data.vorbis_comment.num_comments);
  1037. if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length))
  1038. return false;
  1039. return vorbiscomment_set_entry_(object, &object->data.vorbis_comment.comments[comment_num], &entry, copy);
  1040. }
  1041. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy)
  1042. {
  1043. FLAC__StreamMetadata_VorbisComment *vc;
  1044. FLAC__ASSERT(0 != object);
  1045. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  1046. FLAC__ASSERT(comment_num <= object->data.vorbis_comment.num_comments);
  1047. if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length))
  1048. return false;
  1049. vc = &object->data.vorbis_comment;
  1050. if(!FLAC__metadata_object_vorbiscomment_resize_comments(object, vc->num_comments+1))
  1051. return false;
  1052. /* move all comments >= comment_num forward one space */
  1053. memmove(&vc->comments[comment_num+1], &vc->comments[comment_num], sizeof(FLAC__StreamMetadata_VorbisComment_Entry)*(vc->num_comments-1-comment_num));
  1054. vc->comments[comment_num].length = 0;
  1055. vc->comments[comment_num].entry = 0;
  1056. return FLAC__metadata_object_vorbiscomment_set_comment(object, comment_num, entry, copy);
  1057. }
  1058. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy)
  1059. {
  1060. FLAC__ASSERT(0 != object);
  1061. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  1062. return FLAC__metadata_object_vorbiscomment_insert_comment(object, object->data.vorbis_comment.num_comments, entry, copy);
  1063. }
  1064. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_replace_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool all, FLAC__bool copy)
  1065. {
  1066. FLAC__ASSERT(0 != entry.entry && entry.length > 0);
  1067. if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length))
  1068. return false;
  1069. {
  1070. int i;
  1071. size_t field_name_length;
  1072. const FLAC__byte *eq = (FLAC__byte*)memchr(entry.entry, '=', entry.length);
  1073. FLAC__ASSERT(0 != eq);
  1074. if(0 == eq)
  1075. return false; /* double protection */
  1076. field_name_length = eq-entry.entry;
  1077. if((i = vorbiscomment_find_entry_from_(object, 0, (const char *)entry.entry, field_name_length)) >= 0) {
  1078. unsigned index = (unsigned)i;
  1079. if(!FLAC__metadata_object_vorbiscomment_set_comment(object, index, entry, copy))
  1080. return false;
  1081. if(all && (index+1 < object->data.vorbis_comment.num_comments)) {
  1082. for(i = vorbiscomment_find_entry_from_(object, index+1, (const char *)entry.entry, field_name_length); i >= 0; ) {
  1083. if(!FLAC__metadata_object_vorbiscomment_delete_comment(object, (unsigned)i))
  1084. return false;
  1085. if((unsigned)i < object->data.vorbis_comment.num_comments)
  1086. i = vorbiscomment_find_entry_from_(object, (unsigned)i, (const char *)entry.entry, field_name_length);
  1087. else
  1088. i = -1;
  1089. }
  1090. }
  1091. return true;
  1092. }
  1093. else
  1094. return FLAC__metadata_object_vorbiscomment_append_comment(object, entry, copy);
  1095. }
  1096. }
  1097. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num)
  1098. {
  1099. FLAC__StreamMetadata_VorbisComment *vc;
  1100. FLAC__ASSERT(0 != object);
  1101. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  1102. FLAC__ASSERT(comment_num < object->data.vorbis_comment.num_comments);
  1103. vc = &object->data.vorbis_comment;
  1104. /* free the comment at comment_num */
  1105. if(0 != vc->comments[comment_num].entry)
  1106. free(vc->comments[comment_num].entry);
  1107. /* move all comments > comment_num backward one space */
  1108. memmove(&vc->comments[comment_num], &vc->comments[comment_num+1], sizeof(FLAC__StreamMetadata_VorbisComment_Entry)*(vc->num_comments-comment_num-1));
  1109. vc->comments[vc->num_comments-1].length = 0;
  1110. vc->comments[vc->num_comments-1].entry = 0;
  1111. return FLAC__metadata_object_vorbiscomment_resize_comments(object, vc->num_comments-1);
  1112. }
  1113. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *field_name, const char *field_value)
  1114. {
  1115. FLAC__ASSERT(0 != entry);
  1116. FLAC__ASSERT(0 != field_name);
  1117. FLAC__ASSERT(0 != field_value);
  1118. if(!FLAC__format_vorbiscomment_entry_name_is_legal(field_name))
  1119. return false;
  1120. if(!FLAC__format_vorbiscomment_entry_value_is_legal((const FLAC__byte *)field_value, (unsigned)(-1)))
  1121. return false;
  1122. {
  1123. const size_t nn = strlen(field_name);
  1124. const size_t nv = strlen(field_value);
  1125. entry->length = nn + 1 /*=*/ + nv;
  1126. if(0 == (entry->entry = (FLAC__byte*)safe_malloc_add_4op_(nn, /*+*/1, /*+*/nv, /*+*/1)))
  1127. return false;
  1128. memcpy(entry->entry, field_name, nn);
  1129. entry->entry[nn] = '=';
  1130. memcpy(entry->entry+nn+1, field_value, nv);
  1131. entry->entry[entry->length] = '\0';
  1132. }
  1133. return true;
  1134. }
  1135. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(const FLAC__StreamMetadata_VorbisComment_Entry entry, char **field_name, char **field_value)
  1136. {
  1137. FLAC__ASSERT(0 != entry.entry && entry.length > 0);
  1138. FLAC__ASSERT(0 != field_name);
  1139. FLAC__ASSERT(0 != field_value);
  1140. if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length))
  1141. return false;
  1142. {
  1143. const FLAC__byte *eq = (FLAC__byte*)memchr(entry.entry, '=', entry.length);
  1144. const size_t nn = eq-entry.entry;
  1145. const size_t nv = entry.length-nn-1; /* -1 for the '=' */
  1146. FLAC__ASSERT(0 != eq);
  1147. if(0 == eq)
  1148. return false; /* double protection */
  1149. if(0 == (*field_name = (char*)safe_malloc_add_2op_(nn, /*+*/1)))
  1150. return false;
  1151. if(0 == (*field_value = (char*)safe_malloc_add_2op_(nv, /*+*/1))) {
  1152. free(*field_name);
  1153. return false;
  1154. }
  1155. memcpy(*field_name, entry.entry, nn);
  1156. memcpy(*field_value, entry.entry+nn+1, nv);
  1157. (*field_name)[nn] = '\0';
  1158. (*field_value)[nv] = '\0';
  1159. }
  1160. return true;
  1161. }
  1162. FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, unsigned field_name_length)
  1163. {
  1164. FLAC__ASSERT(0 != entry.entry && entry.length > 0);
  1165. {
  1166. const FLAC__byte *eq = (FLAC__byte*)memchr(entry.entry, '=', entry.length);
  1167. #if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__
  1168. #define FLAC__STRNCASECMP strnicmp
  1169. #else
  1170. #define FLAC__STRNCASECMP strncasecmp
  1171. #endif
  1172. return (0 != eq && (unsigned)(eq-entry.entry) == field_name_length && 0 == FLAC__STRNCASECMP(field_name, (const char *)entry.entry, field_name_length));
  1173. #undef FLAC__STRNCASECMP
  1174. }
  1175. }
  1176. FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name)
  1177. {
  1178. FLAC__ASSERT(0 != field_name);
  1179. return vorbiscomment_find_entry_from_(object, offset, field_name, strlen(field_name));
  1180. }
  1181. FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entry_matching(FLAC__StreamMetadata *object, const char *field_name)
  1182. {
  1183. const unsigned field_name_length = strlen(field_name);
  1184. unsigned i;
  1185. FLAC__ASSERT(0 != object);
  1186. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  1187. for(i = 0; i < object->data.vorbis_comment.num_comments; i++) {
  1188. if(FLAC__metadata_object_vorbiscomment_entry_matches(object->data.vorbis_comment.comments[i], field_name, field_name_length)) {
  1189. if(!FLAC__metadata_object_vorbiscomment_delete_comment(object, i))
  1190. return -1;
  1191. else
  1192. return 1;
  1193. }
  1194. }
  1195. return 0;
  1196. }
  1197. FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__StreamMetadata *object, const char *field_name)
  1198. {
  1199. FLAC__bool ok = true;
  1200. unsigned matching = 0;
  1201. const unsigned field_name_length = strlen(field_name);
  1202. int i;
  1203. FLAC__ASSERT(0 != object);
  1204. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  1205. /* must delete from end to start otherwise it will interfere with our iteration */
  1206. for(i = (int)object->data.vorbis_comment.num_comments - 1; ok && i >= 0; i--) {
  1207. if(FLAC__metadata_object_vorbiscomment_entry_matches(object->data.vorbis_comment.comments[i], field_name, field_name_length)) {
  1208. matching++;
  1209. ok &= FLAC__metadata_object_vorbiscomment_delete_comment(object, (unsigned)i);
  1210. }
  1211. }
  1212. return ok? (int)matching : -1;
  1213. }
  1214. FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void)
  1215. {
  1216. return (FLAC__StreamMetadata_CueSheet_Track*)calloc(1, sizeof(FLAC__StreamMetadata_CueSheet_Track));
  1217. }
  1218. FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_clone(const FLAC__StreamMetadata_CueSheet_Track *object)
  1219. {
  1220. FLAC__StreamMetadata_CueSheet_Track *to;
  1221. FLAC__ASSERT(0 != object);
  1222. if(0 != (to = FLAC__metadata_object_cuesheet_track_new())) {
  1223. if(!copy_track_(to, object)) {
  1224. FLAC__metadata_object_cuesheet_track_delete(to);
  1225. return 0;
  1226. }
  1227. }
  1228. return to;
  1229. }
  1230. void FLAC__metadata_object_cuesheet_track_delete_data(FLAC__StreamMetadata_CueSheet_Track *object)
  1231. {
  1232. FLAC__ASSERT(0 != object);
  1233. if(0 != object->indices) {
  1234. FLAC__ASSERT(object->num_indices > 0);
  1235. free(object->indices);
  1236. }
  1237. }
  1238. FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_CueSheet_Track *object)
  1239. {
  1240. FLAC__metadata_object_cuesheet_track_delete_data(object);
  1241. free(object);
  1242. }
  1243. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices)
  1244. {
  1245. FLAC__StreamMetadata_CueSheet_Track *track;
  1246. FLAC__ASSERT(0 != object);
  1247. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1248. FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
  1249. track = &object->data.cue_sheet.tracks[track_num];
  1250. if(0 == track->indices) {
  1251. FLAC__ASSERT(track->num_indices == 0);
  1252. if(0 == new_num_indices)
  1253. return true;
  1254. else if(0 == (track->indices = cuesheet_track_index_array_new_(new_num_indices)))
  1255. return false;
  1256. }
  1257. else {
  1258. const size_t old_size = track->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index);
  1259. const size_t new_size = new_num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index);
  1260. /* overflow check */
  1261. if((size_t)new_num_indices > SIZE_MAX / sizeof(FLAC__StreamMetadata_CueSheet_Index))
  1262. return false;
  1263. FLAC__ASSERT(track->num_indices > 0);
  1264. if(new_size == 0) {
  1265. free(track->indices);
  1266. track->indices = 0;
  1267. }
  1268. else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)realloc(track->indices, new_size)))
  1269. return false;
  1270. /* if growing, zero all the lengths/pointers of new elements */
  1271. if(new_size > old_size)
  1272. memset(track->indices + track->num_indices, 0, new_size - old_size);
  1273. }
  1274. track->num_indices = new_num_indices;
  1275. cuesheet_calculate_length_(object);
  1276. return true;
  1277. }
  1278. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index)
  1279. {
  1280. FLAC__StreamMetadata_CueSheet_Track *track;
  1281. FLAC__ASSERT(0 != object);
  1282. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1283. FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
  1284. FLAC__ASSERT(index_num <= object->data.cue_sheet.tracks[track_num].num_indices);
  1285. track = &object->data.cue_sheet.tracks[track_num];
  1286. if(!FLAC__metadata_object_cuesheet_track_resize_indices(object, track_num, track->num_indices+1))
  1287. return false;
  1288. /* move all indices >= index_num forward one space */
  1289. memmove(&track->indices[index_num+1], &track->indices[index_num], sizeof(FLAC__StreamMetadata_CueSheet_Index)*(track->num_indices-1-index_num));
  1290. track->indices[index_num] = index;
  1291. cuesheet_calculate_length_(object);
  1292. return true;
  1293. }
  1294. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num)
  1295. {
  1296. FLAC__StreamMetadata_CueSheet_Index index;
  1297. memset(&index, 0, sizeof(index));
  1298. return FLAC__metadata_object_cuesheet_track_insert_index(object, track_num, index_num, index);
  1299. }
  1300. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num)
  1301. {
  1302. FLAC__StreamMetadata_CueSheet_Track *track;
  1303. FLAC__ASSERT(0 != object);
  1304. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1305. FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
  1306. FLAC__ASSERT(index_num < object->data.cue_sheet.tracks[track_num].num_indices);
  1307. track = &object->data.cue_sheet.tracks[track_num];
  1308. /* move all indices > index_num backward one space */
  1309. memmove(&track->indices[index_num], &track->indices[index_num+1], sizeof(FLAC__StreamMetadata_CueSheet_Index)*(track->num_indices-index_num-1));
  1310. FLAC__metadata_object_cuesheet_track_resize_indices(object, track_num, track->num_indices-1);
  1311. cuesheet_calculate_length_(object);
  1312. return true;
  1313. }
  1314. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks)
  1315. {
  1316. FLAC__ASSERT(0 != object);
  1317. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1318. if(0 == object->data.cue_sheet.tracks) {
  1319. FLAC__ASSERT(object->data.cue_sheet.num_tracks == 0);
  1320. if(0 == new_num_tracks)
  1321. return true;
  1322. else if(0 == (object->data.cue_sheet.tracks = cuesheet_track_array_new_(new_num_tracks)))
  1323. return false;
  1324. }
  1325. else {
  1326. const size_t old_size = object->data.cue_sheet.num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track);
  1327. const size_t new_size = new_num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track);
  1328. /* overflow check */
  1329. if((size_t)new_num_tracks > SIZE_MAX / sizeof(FLAC__StreamMetadata_CueSheet_Track))
  1330. return false;
  1331. FLAC__ASSERT(object->data.cue_sheet.num_tracks > 0);
  1332. /* if shrinking, free the truncated entries */
  1333. if(new_num_tracks < object->data.cue_sheet.num_tracks) {
  1334. unsigned i;
  1335. for(i = new_num_tracks; i < object->data.cue_sheet.num_tracks; i++)
  1336. if(0 != object->data.cue_sheet.tracks[i].indices)
  1337. free(object->data.cue_sheet.tracks[i].indices);
  1338. }
  1339. if(new_size == 0) {
  1340. free(object->data.cue_sheet.tracks);
  1341. object->data.cue_sheet.tracks = 0;
  1342. }
  1343. else if(0 == (object->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)realloc(object->data.cue_sheet.tracks, new_size)))
  1344. return false;
  1345. /* if growing, zero all the lengths/pointers of new elements */
  1346. if(new_size > old_size)
  1347. memset(object->data.cue_sheet.tracks + object->data.cue_sheet.num_tracks, 0, new_size - old_size);
  1348. }
  1349. object->data.cue_sheet.num_tracks = new_num_tracks;
  1350. cuesheet_calculate_length_(object);
  1351. return true;
  1352. }
  1353. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy)
  1354. {
  1355. FLAC__ASSERT(0 != object);
  1356. FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
  1357. return cuesheet_set_track_(object, object->data.cue_sheet.tracks + track_num, track, copy);
  1358. }
  1359. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy)
  1360. {
  1361. FLAC__StreamMetadata_CueSheet *cs;
  1362. FLAC__ASSERT(0 != object);
  1363. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1364. FLAC__ASSERT(track_num <= object->data.cue_sheet.num_tracks);
  1365. cs = &object->data.cue_sheet;
  1366. if(!FLAC__metadata_object_cuesheet_resize_tracks(object, cs->num_tracks+1))
  1367. return false;
  1368. /* move all tracks >= track_num forward one space */
  1369. memmove(&cs->tracks[track_num+1], &cs->tracks[track_num], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(cs->num_tracks-1-track_num));
  1370. cs->tracks[track_num].num_indices = 0;
  1371. cs->tracks[track_num].indices = 0;
  1372. return FLAC__metadata_object_cuesheet_set_track(object, track_num, track, copy);
  1373. }
  1374. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, unsigned track_num)
  1375. {
  1376. FLAC__StreamMetadata_CueSheet_Track track;
  1377. memset(&track, 0, sizeof(track));
  1378. return FLAC__metadata_object_cuesheet_insert_track(object, track_num, &track, /*copy=*/false);
  1379. }
  1380. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num)
  1381. {
  1382. FLAC__StreamMetadata_CueSheet *cs;
  1383. FLAC__ASSERT(0 != object);
  1384. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1385. FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
  1386. cs = &object->data.cue_sheet;
  1387. /* free the track at track_num */
  1388. if(0 != cs->tracks[track_num].indices)
  1389. free(cs->tracks[track_num].indices);
  1390. /* move all tracks > track_num backward one space */
  1391. memmove(&cs->tracks[track_num], &cs->tracks[track_num+1], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(cs->num_tracks-track_num-1));
  1392. cs->tracks[cs->num_tracks-1].num_indices = 0;
  1393. cs->tracks[cs->num_tracks-1].indices = 0;
  1394. return FLAC__metadata_object_cuesheet_resize_tracks(object, cs->num_tracks-1);
  1395. }
  1396. FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMetadata *object, FLAC__bool check_cd_da_subset, const char **violation)
  1397. {
  1398. FLAC__ASSERT(0 != object);
  1399. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1400. return FLAC__format_cuesheet_is_legal(&object->data.cue_sheet, check_cd_da_subset, violation);
  1401. }
  1402. static FLAC__uint64 get_index_01_offset_(const FLAC__StreamMetadata_CueSheet *cs, unsigned track)
  1403. {
  1404. if (track >= (cs->num_tracks-1) || cs->tracks[track].num_indices < 1)
  1405. return 0;
  1406. else if (cs->tracks[track].indices[0].number == 1)
  1407. return cs->tracks[track].indices[0].offset + cs->tracks[track].offset + cs->lead_in;
  1408. else if (cs->tracks[track].num_indices < 2)
  1409. return 0;
  1410. else if (cs->tracks[track].indices[1].number == 1)
  1411. return cs->tracks[track].indices[1].offset + cs->tracks[track].offset + cs->lead_in;
  1412. else
  1413. return 0;
  1414. }
  1415. static FLAC__uint32 cddb_add_digits_(FLAC__uint32 x)
  1416. {
  1417. FLAC__uint32 n = 0;
  1418. while (x) {
  1419. n += (x%10);
  1420. x /= 10;
  1421. }
  1422. return n;
  1423. }
  1424. /*@@@@add to tests*/
  1425. FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object)
  1426. {
  1427. const FLAC__StreamMetadata_CueSheet *cs;
  1428. FLAC__ASSERT(0 != object);
  1429. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
  1430. cs = &object->data.cue_sheet;
  1431. if (cs->num_tracks < 2) /* need at least one real track and the lead-out track */
  1432. return 0;
  1433. {
  1434. FLAC__uint32 i, length, sum = 0;
  1435. for (i = 0; i < (cs->num_tracks-1); i++) /* -1 to avoid counting the lead-out */
  1436. sum += cddb_add_digits_((FLAC__uint32)(get_index_01_offset_(cs, i) / 44100));
  1437. length = (FLAC__uint32)((cs->tracks[cs->num_tracks-1].offset+cs->lead_in) / 44100) - (FLAC__uint32)(get_index_01_offset_(cs, 0) / 44100);
  1438. return (sum % 0xFF) << 24 | length << 8 | (FLAC__uint32)(cs->num_tracks-1);
  1439. }
  1440. }
  1441. FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy)
  1442. {
  1443. char *old;
  1444. size_t old_length, new_length;
  1445. FLAC__ASSERT(0 != object);
  1446. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
  1447. FLAC__ASSERT(0 != mime_type);
  1448. old = object->data.picture.mime_type;
  1449. old_length = old? strlen(old) : 0;
  1450. new_length = strlen(mime_type);
  1451. /* do the copy first so that if we fail we leave the object untouched */
  1452. if(copy) {
  1453. if(new_length >= SIZE_MAX) /* overflow check */
  1454. return false;
  1455. if(!copy_bytes_((FLAC__byte**)(&object->data.picture.mime_type), (FLAC__byte*)mime_type, new_length+1))
  1456. return false;
  1457. }
  1458. else {
  1459. object->data.picture.mime_type = mime_type;
  1460. }
  1461. if(0 != old)
  1462. free(old);
  1463. object->length -= old_length;
  1464. object->length += new_length;
  1465. return true;
  1466. }
  1467. FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy)
  1468. {
  1469. FLAC__byte *old;
  1470. size_t old_length, new_length;
  1471. FLAC__ASSERT(0 != object);
  1472. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
  1473. FLAC__ASSERT(0 != description);
  1474. old = object->data.picture.description;
  1475. old_length = old? strlen((const char *)old) : 0;
  1476. new_length = strlen((const char *)description);
  1477. /* do the copy first so that if we fail we leave the object untouched */
  1478. if(copy) {
  1479. if(new_length >= SIZE_MAX) /* overflow check */
  1480. return false;
  1481. if(!copy_bytes_(&object->data.picture.description, description, new_length+1))
  1482. return false;
  1483. }
  1484. else {
  1485. object->data.picture.description = description;
  1486. }
  1487. if(0 != old)
  1488. free(old);
  1489. object->length -= old_length;
  1490. object->length += new_length;
  1491. return true;
  1492. }
  1493. FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy)
  1494. {
  1495. FLAC__byte *old;
  1496. FLAC__ASSERT(0 != object);
  1497. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
  1498. FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
  1499. old = object->data.picture.data;
  1500. /* do the copy first so that if we fail we leave the object untouched */
  1501. if(copy) {
  1502. if(!copy_bytes_(&object->data.picture.data, data, length))
  1503. return false;
  1504. }
  1505. else {
  1506. object->data.picture.data = data;
  1507. }
  1508. if(0 != old)
  1509. free(old);
  1510. object->length -= object->data.picture.data_length;
  1511. object->data.picture.data_length = length;
  1512. object->length += length;
  1513. return true;
  1514. }
  1515. FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation)
  1516. {
  1517. FLAC__ASSERT(0 != object);
  1518. FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
  1519. return FLAC__format_picture_is_legal(&object->data.picture, violation);
  1520. }