metadata.cpp
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:35k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* libFLAC++ - Free Lossless Audio Codec library
  2.  * Copyright (C) 2002,2003,2004,2005  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. #include "FLAC++/metadata.h"
  32. #include "FLAC/assert.h"
  33. #include <stdlib.h> // for malloc(), free()
  34. #include <string.h> // for memcpy() etc.
  35. #ifdef _MSC_VER
  36. // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
  37. #pragma warning ( disable : 4800 )
  38. #endif
  39. namespace FLAC {
  40. namespace Metadata {
  41. // local utility routines
  42. namespace local {
  43. Prototype *construct_block(::FLAC__StreamMetadata *object)
  44. {
  45. Prototype *ret = 0;
  46. switch(object->type) {
  47. case FLAC__METADATA_TYPE_STREAMINFO:
  48. ret = new StreamInfo(object, /*copy=*/false);
  49. break;
  50. case FLAC__METADATA_TYPE_PADDING:
  51. ret = new Padding(object, /*copy=*/false);
  52. break;
  53. case FLAC__METADATA_TYPE_APPLICATION:
  54. ret = new Application(object, /*copy=*/false);
  55. break;
  56. case FLAC__METADATA_TYPE_SEEKTABLE:
  57. ret = new SeekTable(object, /*copy=*/false);
  58. break;
  59. case FLAC__METADATA_TYPE_VORBIS_COMMENT:
  60. ret = new VorbisComment(object, /*copy=*/false);
  61. break;
  62. case FLAC__METADATA_TYPE_CUESHEET:
  63. ret = new CueSheet(object, /*copy=*/false);
  64. break;
  65. default:
  66. ret = new Unknown(object, /*copy=*/false);
  67. break;
  68. }
  69. return ret;
  70. }
  71. }
  72. FLACPP_API Prototype *clone(const Prototype *object)
  73. {
  74. FLAC__ASSERT(0 != object);
  75. const StreamInfo *streaminfo = dynamic_cast<const StreamInfo *>(object);
  76. const Padding *padding = dynamic_cast<const Padding *>(object);
  77. const Application *application = dynamic_cast<const Application *>(object);
  78. const SeekTable *seektable = dynamic_cast<const SeekTable *>(object);
  79. const VorbisComment *vorbiscomment = dynamic_cast<const VorbisComment *>(object);
  80. const CueSheet *cuesheet = dynamic_cast<const CueSheet *>(object);
  81. const Unknown *unknown = dynamic_cast<const Unknown *>(object);
  82. if(0 != streaminfo)
  83. return new StreamInfo(*streaminfo);
  84. else if(0 != padding)
  85. return new Padding(*padding);
  86. else if(0 != application)
  87. return new Application(*application);
  88. else if(0 != seektable)
  89. return new SeekTable(*seektable);
  90. else if(0 != vorbiscomment)
  91. return new VorbisComment(*vorbiscomment);
  92. else if(0 != cuesheet)
  93. return new CueSheet(*cuesheet);
  94. else if(0 != unknown)
  95. return new Unknown(*unknown);
  96. else {
  97. FLAC__ASSERT(0);
  98. return 0;
  99. }
  100. }
  101. //
  102. // Prototype
  103. //
  104. Prototype::Prototype(const Prototype &object):
  105. object_(::FLAC__metadata_object_clone(object.object_)),
  106. is_reference_(false)
  107. {
  108. FLAC__ASSERT(object.is_valid());
  109. }
  110. Prototype::Prototype(const ::FLAC__StreamMetadata &object):
  111. object_(::FLAC__metadata_object_clone(&object)),
  112. is_reference_(false)
  113. {
  114. }
  115. Prototype::Prototype(const ::FLAC__StreamMetadata *object):
  116. object_(::FLAC__metadata_object_clone(object)),
  117. is_reference_(false)
  118. {
  119. FLAC__ASSERT(0 != object);
  120. }
  121. Prototype::Prototype(::FLAC__StreamMetadata *object, bool copy):
  122. object_(copy? ::FLAC__metadata_object_clone(object) : object),
  123. is_reference_(false)
  124. {
  125. FLAC__ASSERT(0 != object);
  126. }
  127. Prototype::~Prototype()
  128. {
  129. clear();
  130. }
  131. void Prototype::clear()
  132. {
  133. if(0 != object_ && !is_reference_)
  134. FLAC__metadata_object_delete(object_);
  135. object_ = 0;
  136. }
  137. Prototype &Prototype::operator=(const Prototype &object)
  138. {
  139. FLAC__ASSERT(object.is_valid());
  140. clear();
  141. is_reference_ = false;
  142. object_ = ::FLAC__metadata_object_clone(object.object_);
  143. return *this;
  144. }
  145. Prototype &Prototype::operator=(const ::FLAC__StreamMetadata &object)
  146. {
  147. clear();
  148. is_reference_ = false;
  149. object_ = ::FLAC__metadata_object_clone(&object);
  150. return *this;
  151. }
  152. Prototype &Prototype::operator=(const ::FLAC__StreamMetadata *object)
  153. {
  154. FLAC__ASSERT(0 != object);
  155. clear();
  156. is_reference_ = false;
  157. object_ = ::FLAC__metadata_object_clone(object);
  158. return *this;
  159. }
  160. Prototype &Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy)
  161. {
  162. FLAC__ASSERT(0 != object);
  163. clear();
  164. object_ = (copy? ::FLAC__metadata_object_clone(object) : object);
  165. is_reference_ = false;
  166. return *this;
  167. }
  168. bool Prototype::get_is_last() const
  169. {
  170. FLAC__ASSERT(is_valid());
  171. return (bool)object_->is_last;
  172. }
  173. FLAC__MetadataType Prototype::get_type() const
  174. {
  175. FLAC__ASSERT(is_valid());
  176. return object_->type;
  177. }
  178. unsigned Prototype::get_length() const
  179. {
  180. FLAC__ASSERT(is_valid());
  181. return object_->length;
  182. }
  183. void Prototype::set_is_last(bool value)
  184. {
  185. FLAC__ASSERT(is_valid());
  186. object_->is_last = value;
  187. }
  188. //
  189. // StreamInfo
  190. //
  191. StreamInfo::StreamInfo():
  192. Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO), /*copy=*/false)
  193. { }
  194. StreamInfo::~StreamInfo()
  195. { }
  196. unsigned StreamInfo::get_min_blocksize() const
  197. {
  198. FLAC__ASSERT(is_valid());
  199. return object_->data.stream_info.min_blocksize;
  200. }
  201. unsigned StreamInfo::get_max_blocksize() const
  202. {
  203. FLAC__ASSERT(is_valid());
  204. return object_->data.stream_info.max_blocksize;
  205. }
  206. unsigned StreamInfo::get_min_framesize() const
  207. {
  208. FLAC__ASSERT(is_valid());
  209. return object_->data.stream_info.min_framesize;
  210. }
  211. unsigned StreamInfo::get_max_framesize() const
  212. {
  213. FLAC__ASSERT(is_valid());
  214. return object_->data.stream_info.max_framesize;
  215. }
  216. unsigned StreamInfo::get_sample_rate() const
  217. {
  218. FLAC__ASSERT(is_valid());
  219. return object_->data.stream_info.sample_rate;
  220. }
  221. unsigned StreamInfo::get_channels() const
  222. {
  223. FLAC__ASSERT(is_valid());
  224. return object_->data.stream_info.channels;
  225. }
  226. unsigned StreamInfo::get_bits_per_sample() const
  227. {
  228. FLAC__ASSERT(is_valid());
  229. return object_->data.stream_info.bits_per_sample;
  230. }
  231. FLAC__uint64 StreamInfo::get_total_samples() const
  232. {
  233. FLAC__ASSERT(is_valid());
  234. return object_->data.stream_info.total_samples;
  235. }
  236. const FLAC__byte *StreamInfo::get_md5sum() const
  237. {
  238. FLAC__ASSERT(is_valid());
  239. return object_->data.stream_info.md5sum;
  240. }
  241. void StreamInfo::set_min_blocksize(unsigned value)
  242. {
  243. FLAC__ASSERT(is_valid());
  244. FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
  245. FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
  246. object_->data.stream_info.min_blocksize = value;
  247. }
  248. void StreamInfo::set_max_blocksize(unsigned value)
  249. {
  250. FLAC__ASSERT(is_valid());
  251. FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
  252. FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
  253. object_->data.stream_info.max_blocksize = value;
  254. }
  255. void StreamInfo::set_min_framesize(unsigned value)
  256. {
  257. FLAC__ASSERT(is_valid());
  258. FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
  259. object_->data.stream_info.min_framesize = value;
  260. }
  261. void StreamInfo::set_max_framesize(unsigned value)
  262. {
  263. FLAC__ASSERT(is_valid());
  264. FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
  265. object_->data.stream_info.max_framesize = value;
  266. }
  267. void StreamInfo::set_sample_rate(unsigned value)
  268. {
  269. FLAC__ASSERT(is_valid());
  270. FLAC__ASSERT(FLAC__format_sample_rate_is_valid(value));
  271. object_->data.stream_info.sample_rate = value;
  272. }
  273. void StreamInfo::set_channels(unsigned value)
  274. {
  275. FLAC__ASSERT(is_valid());
  276. FLAC__ASSERT(value > 0);
  277. FLAC__ASSERT(value <= FLAC__MAX_CHANNELS);
  278. object_->data.stream_info.channels = value;
  279. }
  280. void StreamInfo::set_bits_per_sample(unsigned value)
  281. {
  282. FLAC__ASSERT(is_valid());
  283. FLAC__ASSERT(value >= FLAC__MIN_BITS_PER_SAMPLE);
  284. FLAC__ASSERT(value <= FLAC__MAX_BITS_PER_SAMPLE);
  285. object_->data.stream_info.bits_per_sample = value;
  286. }
  287. void StreamInfo::set_total_samples(FLAC__uint64 value)
  288. {
  289. FLAC__ASSERT(is_valid());
  290. FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN));
  291. object_->data.stream_info.total_samples = value;
  292. }
  293. void StreamInfo::set_md5sum(const FLAC__byte value[16])
  294. {
  295. FLAC__ASSERT(is_valid());
  296. FLAC__ASSERT(0 != value);
  297. memcpy(object_->data.stream_info.md5sum, value, 16);
  298. }
  299. //
  300. // Padding
  301. //
  302. Padding::Padding():
  303. Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false)
  304. { }
  305. Padding::~Padding()
  306. { }
  307. void Padding::set_length(unsigned length)
  308. {
  309. FLAC__ASSERT(is_valid());
  310. object_->length = length;
  311. }
  312. //
  313. // Application
  314. //
  315. Application::Application():
  316. Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
  317. { }
  318. Application::~Application()
  319. { }
  320. const FLAC__byte *Application::get_id() const
  321. {
  322. FLAC__ASSERT(is_valid());
  323. return object_->data.application.id;
  324. }
  325. const FLAC__byte *Application::get_data() const
  326. {
  327. FLAC__ASSERT(is_valid());
  328. return object_->data.application.data;
  329. }
  330. void Application::set_id(const FLAC__byte value[4])
  331. {
  332. FLAC__ASSERT(is_valid());
  333. FLAC__ASSERT(0 != value);
  334. memcpy(object_->data.application.id, value, 4);
  335. }
  336. bool Application::set_data(const FLAC__byte *data, unsigned length)
  337. {
  338. FLAC__ASSERT(is_valid());
  339. return (bool)::FLAC__metadata_object_application_set_data(object_, (FLAC__byte*)data, length, true);
  340. }
  341. bool Application::set_data(FLAC__byte *data, unsigned length, bool copy)
  342. {
  343. FLAC__ASSERT(is_valid());
  344. return (bool)::FLAC__metadata_object_application_set_data(object_, data, length, copy);
  345. }
  346. //
  347. // SeekTable
  348. //
  349. SeekTable::SeekTable():
  350. Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE), /*copy=*/false)
  351. { }
  352. SeekTable::~SeekTable()
  353. { }
  354. unsigned SeekTable::get_num_points() const
  355. {
  356. FLAC__ASSERT(is_valid());
  357. return object_->data.seek_table.num_points;
  358. }
  359. ::FLAC__StreamMetadata_SeekPoint SeekTable::get_point(unsigned index) const
  360. {
  361. FLAC__ASSERT(is_valid());
  362. FLAC__ASSERT(index < object_->data.seek_table.num_points);
  363. return object_->data.seek_table.points[index];
  364. }
  365. void SeekTable::set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point)
  366. {
  367. FLAC__ASSERT(is_valid());
  368. FLAC__ASSERT(index < object_->data.seek_table.num_points);
  369. ::FLAC__metadata_object_seektable_set_point(object_, index, point);
  370. }
  371. bool SeekTable::insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point)
  372. {
  373. FLAC__ASSERT(is_valid());
  374. FLAC__ASSERT(index <= object_->data.seek_table.num_points);
  375. return (bool)::FLAC__metadata_object_seektable_insert_point(object_, index, point);
  376. }
  377. bool SeekTable::delete_point(unsigned index)
  378. {
  379. FLAC__ASSERT(is_valid());
  380. FLAC__ASSERT(index < object_->data.seek_table.num_points);
  381. return (bool)::FLAC__metadata_object_seektable_delete_point(object_, index);
  382. }
  383. bool SeekTable::is_legal() const
  384. {
  385. FLAC__ASSERT(is_valid());
  386. return (bool)::FLAC__metadata_object_seektable_is_legal(object_);
  387. }
  388. //
  389. // VorbisComment::Entry
  390. //
  391. VorbisComment::Entry::Entry()
  392. {
  393. zero();
  394. }
  395. VorbisComment::Entry::Entry(const char *field, unsigned field_length)
  396. {
  397. zero();
  398. construct(field, field_length);
  399. }
  400. VorbisComment::Entry::Entry(const char *field)
  401. {
  402. zero();
  403. construct(field);
  404. }
  405. VorbisComment::Entry::Entry(const char *field_name, const char *field_value, unsigned field_value_length)
  406. {
  407. zero();
  408. construct(field_name, field_value, field_value_length);
  409. }
  410. VorbisComment::Entry::Entry(const char *field_name, const char *field_value)
  411. {
  412. zero();
  413. construct(field_name, field_value);
  414. }
  415. VorbisComment::Entry::Entry(const Entry &entry)
  416. {
  417. FLAC__ASSERT(entry.is_valid());
  418. zero();
  419. construct((const char *)entry.entry_.entry, entry.entry_.length);
  420. }
  421. VorbisComment::Entry &VorbisComment::Entry::operator=(const Entry &entry)
  422. {
  423. FLAC__ASSERT(entry.is_valid());
  424. clear();
  425. construct((const char *)entry.entry_.entry, entry.entry_.length);
  426. return *this;
  427. }
  428. VorbisComment::Entry::~Entry()
  429. {
  430. clear();
  431. }
  432. bool VorbisComment::Entry::is_valid() const
  433. {
  434. return is_valid_;
  435. }
  436. unsigned VorbisComment::Entry::get_field_length() const
  437. {
  438. FLAC__ASSERT(is_valid());
  439. return entry_.length;
  440. }
  441. unsigned VorbisComment::Entry::get_field_name_length() const
  442. {
  443. FLAC__ASSERT(is_valid());
  444. return field_name_length_;
  445. }
  446. unsigned VorbisComment::Entry::get_field_value_length() const
  447. {
  448. FLAC__ASSERT(is_valid());
  449. return field_value_length_;
  450. }
  451. ::FLAC__StreamMetadata_VorbisComment_Entry VorbisComment::Entry::get_entry() const
  452. {
  453. FLAC__ASSERT(is_valid());
  454. return entry_;
  455. }
  456. const char *VorbisComment::Entry::get_field() const
  457. {
  458. FLAC__ASSERT(is_valid());
  459. return (const char *)entry_.entry;
  460. }
  461. const char *VorbisComment::Entry::get_field_name() const
  462. {
  463. FLAC__ASSERT(is_valid());
  464. return field_name_;
  465. }
  466. const char *VorbisComment::Entry::get_field_value() const
  467. {
  468. FLAC__ASSERT(is_valid());
  469. return field_value_;
  470. }
  471. bool VorbisComment::Entry::set_field(const char *field, unsigned field_length)
  472. {
  473. FLAC__ASSERT(is_valid());
  474. FLAC__ASSERT(0 != field);
  475. if(!::FLAC__format_vorbiscomment_entry_is_legal((const ::FLAC__byte*)field, field_length))
  476. return is_valid_ = false;
  477. clear_entry();
  478. if(0 == (entry_.entry = (FLAC__byte*)malloc(field_length+1))) {
  479. is_valid_ = false;
  480. }
  481. else {
  482. entry_.length = field_length;
  483. memcpy(entry_.entry, field, field_length);
  484. entry_.entry[field_length] = '';
  485. (void) parse_field();
  486. }
  487. return is_valid_;
  488. }
  489. bool VorbisComment::Entry::set_field(const char *field)
  490. {
  491. return set_field(field, strlen(field));
  492. }
  493. bool VorbisComment::Entry::set_field_name(const char *field_name)
  494. {
  495. FLAC__ASSERT(is_valid());
  496. FLAC__ASSERT(0 != field_name);
  497. if(!::FLAC__format_vorbiscomment_entry_name_is_legal(field_name))
  498. return is_valid_ = false;
  499. clear_field_name();
  500. if(0 == (field_name_ = strdup(field_name))) {
  501. is_valid_ = false;
  502. }
  503. else {
  504. field_name_length_ = strlen(field_name_);
  505. compose_field();
  506. }
  507. return is_valid_;
  508. }
  509. bool VorbisComment::Entry::set_field_value(const char *field_value, unsigned field_value_length)
  510. {
  511. FLAC__ASSERT(is_valid());
  512. FLAC__ASSERT(0 != field_value);
  513. if(!::FLAC__format_vorbiscomment_entry_value_is_legal((const FLAC__byte*)field_value, field_value_length))
  514. return is_valid_ = false;
  515. clear_field_value();
  516. if(0 == (field_value_ = (char *)malloc(field_value_length+1))) {
  517. is_valid_ = false;
  518. }
  519. else {
  520. field_value_length_ = field_value_length;
  521. memcpy(field_value_, field_value, field_value_length);
  522. field_value_[field_value_length] = '';
  523. compose_field();
  524. }
  525. return is_valid_;
  526. }
  527. bool VorbisComment::Entry::set_field_value(const char *field_value)
  528. {
  529. return set_field_value(field_value, strlen(field_value));
  530. }
  531. void VorbisComment::Entry::zero()
  532. {
  533. is_valid_ = true;
  534. entry_.length = 0;
  535. entry_.entry = 0;
  536. field_name_ = 0;
  537. field_name_length_ = 0;
  538. field_value_ = 0;
  539. field_value_length_ = 0;
  540. }
  541. void VorbisComment::Entry::clear()
  542. {
  543. clear_entry();
  544. clear_field_name();
  545. clear_field_value();
  546. is_valid_ = true;
  547. }
  548. void VorbisComment::Entry::clear_entry()
  549. {
  550. if(0 != entry_.entry) {
  551. free(entry_.entry);
  552. entry_.entry = 0;
  553. entry_.length = 0;
  554. }
  555. }
  556. void VorbisComment::Entry::clear_field_name()
  557. {
  558. if(0 != field_name_) {
  559. free(field_name_);
  560. field_name_ = 0;
  561. field_name_length_ = 0;
  562. }
  563. }
  564. void VorbisComment::Entry::clear_field_value()
  565. {
  566. if(0 != field_value_) {
  567. free(field_value_);
  568. field_value_ = 0;
  569. field_value_length_ = 0;
  570. }
  571. }
  572. void VorbisComment::Entry::construct(const char *field, unsigned field_length)
  573. {
  574. if(set_field(field, field_length))
  575. parse_field();
  576. }
  577. void VorbisComment::Entry::construct(const char *field)
  578. {
  579. construct(field, strlen(field));
  580. }
  581. void VorbisComment::Entry::construct(const char *field_name, const char *field_value, unsigned field_value_length)
  582. {
  583. if(set_field_name(field_name) && set_field_value(field_value, field_value_length))
  584. compose_field();
  585. }
  586. void VorbisComment::Entry::construct(const char *field_name, const char *field_value)
  587. {
  588. construct(field_name, field_value, strlen(field_value));
  589. }
  590. void VorbisComment::Entry::compose_field()
  591. {
  592. clear_entry();
  593. if(0 == (entry_.entry = (FLAC__byte*)malloc(field_name_length_ + 1 + field_value_length_ + 1))) {
  594. is_valid_ = false;
  595. }
  596. else {
  597. memcpy(entry_.entry, field_name_, field_name_length_);
  598. entry_.length += field_name_length_;
  599. memcpy(entry_.entry + entry_.length, "=", 1);
  600. entry_.length += 1;
  601. memcpy(entry_.entry + entry_.length, field_value_, field_value_length_);
  602. entry_.length += field_value_length_;
  603. entry_.entry[entry_.length] = '';
  604. is_valid_ = true;
  605. }
  606. }
  607. void VorbisComment::Entry::parse_field()
  608. {
  609. clear_field_name();
  610. clear_field_value();
  611. const char *p = (const char *)memchr(entry_.entry, '=', entry_.length);
  612. if(0 == p)
  613. p = (const char *)entry_.entry + entry_.length;
  614. field_name_length_ = p - (const char *)entry_.entry;
  615. if(0 == (field_name_ = (char *)malloc(field_name_length_ + 1))) { // +1 for the trailing 
  616. is_valid_ = false;
  617. return;
  618. }
  619. memcpy(field_name_, entry_.entry, field_name_length_);
  620. field_name_[field_name_length_] = '';
  621. if(entry_.length - field_name_length_ == 0) {
  622. field_value_length_ = 0;
  623. if(0 == (field_value_ = (char *)malloc(0))) {
  624. is_valid_ = false;
  625. return;
  626. }
  627. }
  628. else {
  629. field_value_length_ = entry_.length - field_name_length_ - 1;
  630. if(0 == (field_value_ = (char *)malloc(field_value_length_ + 1))) { // +1 for the trailing 
  631. is_valid_ = false;
  632. return;
  633. }
  634. memcpy(field_value_, ++p, field_value_length_);
  635. field_value_[field_value_length_] = '';
  636. }
  637. is_valid_ = true;
  638. }
  639. //
  640. // VorbisComment
  641. //
  642. VorbisComment::VorbisComment():
  643. Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT), /*copy=*/false)
  644. { }
  645. VorbisComment::~VorbisComment()
  646. { }
  647. unsigned VorbisComment::get_num_comments() const
  648. {
  649. FLAC__ASSERT(is_valid());
  650. return object_->data.vorbis_comment.num_comments;
  651. }
  652. const FLAC__byte *VorbisComment::get_vendor_string() const
  653. {
  654. FLAC__ASSERT(is_valid());
  655. return object_->data.vorbis_comment.vendor_string.entry;
  656. }
  657. VorbisComment::Entry VorbisComment::get_comment(unsigned index) const
  658. {
  659. FLAC__ASSERT(is_valid());
  660. FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
  661. return Entry((const char *)object_->data.vorbis_comment.comments[index].entry, object_->data.vorbis_comment.comments[index].length);
  662. }
  663. bool VorbisComment::set_vendor_string(const FLAC__byte *string)
  664. {
  665. FLAC__ASSERT(is_valid());
  666. // vendor_string is a special kind of entry
  667. const ::FLAC__StreamMetadata_VorbisComment_Entry vendor_string = { strlen((const char *)string), (FLAC__byte*)string }; // we can cheat on const-ness because we make a copy below:
  668. return (bool)::FLAC__metadata_object_vorbiscomment_set_vendor_string(object_, vendor_string, /*copy=*/true);
  669. }
  670. bool VorbisComment::set_comment(unsigned index, const VorbisComment::Entry &entry)
  671. {
  672. FLAC__ASSERT(is_valid());
  673. FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
  674. return (bool)::FLAC__metadata_object_vorbiscomment_set_comment(object_, index, entry.get_entry(), /*copy=*/true);
  675. }
  676. bool VorbisComment::insert_comment(unsigned index, const VorbisComment::Entry &entry)
  677. {
  678. FLAC__ASSERT(is_valid());
  679. FLAC__ASSERT(index <= object_->data.vorbis_comment.num_comments);
  680. return (bool)::FLAC__metadata_object_vorbiscomment_insert_comment(object_, index, entry.get_entry(), /*copy=*/true);
  681. }
  682. bool VorbisComment::append_comment(const VorbisComment::Entry &entry)
  683. {
  684. FLAC__ASSERT(is_valid());
  685. return (bool)::FLAC__metadata_object_vorbiscomment_append_comment(object_, entry.get_entry(), /*copy=*/true);
  686. }
  687. bool VorbisComment::delete_comment(unsigned index)
  688. {
  689. FLAC__ASSERT(is_valid());
  690. FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
  691. return (bool)::FLAC__metadata_object_vorbiscomment_delete_comment(object_, index);
  692. }
  693. //
  694. // CueSheet::Track
  695. //
  696. CueSheet::Track::Track():
  697. object_(::FLAC__metadata_object_cuesheet_track_new())
  698. { }
  699. CueSheet::Track::Track(const ::FLAC__StreamMetadata_CueSheet_Track *track):
  700. object_(::FLAC__metadata_object_cuesheet_track_clone(track))
  701. { }
  702. CueSheet::Track::Track(const Track &track):
  703. object_(::FLAC__metadata_object_cuesheet_track_clone(track.object_))
  704. { }
  705. CueSheet::Track &CueSheet::Track::operator=(const Track &track)
  706. {
  707. if(0 != object_)
  708. ::FLAC__metadata_object_cuesheet_track_delete(object_);
  709. object_ = ::FLAC__metadata_object_cuesheet_track_clone(track.object_);
  710. return *this;
  711. }
  712. CueSheet::Track::~Track()
  713. {
  714. if(0 != object_)
  715. ::FLAC__metadata_object_cuesheet_track_delete(object_);
  716. }
  717. bool CueSheet::Track::is_valid() const
  718. {
  719. return(0 != object_);
  720. }
  721. ::FLAC__StreamMetadata_CueSheet_Index CueSheet::Track::get_index(unsigned i) const
  722. {
  723. FLAC__ASSERT(is_valid());
  724. FLAC__ASSERT(i < object_->num_indices);
  725. return object_->indices[i];
  726. }
  727. void CueSheet::Track::set_isrc(const char value[12])
  728. {
  729. FLAC__ASSERT(is_valid());
  730. FLAC__ASSERT(0 != value);
  731. memcpy(object_->isrc, value, 12);
  732. object_->isrc[12] = '';
  733. }
  734. void CueSheet::Track::set_type(unsigned value)
  735. {
  736. FLAC__ASSERT(is_valid());
  737. FLAC__ASSERT(value <= 1);
  738. object_->type = value;
  739. }
  740.   void CueSheet::Track::set_index(unsigned i, const ::FLAC__StreamMetadata_CueSheet_Index &index)
  741.   {
  742.   FLAC__ASSERT(is_valid());
  743.   FLAC__ASSERT(i < object_->num_indices);
  744.   object_->indices[i] = index;
  745.   }
  746. //
  747. // CueSheet
  748. //
  749. CueSheet::CueSheet():
  750. Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET), /*copy=*/false)
  751. { }
  752. CueSheet::~CueSheet()
  753. { }
  754. const char *CueSheet::get_media_catalog_number() const
  755. {
  756. FLAC__ASSERT(is_valid());
  757. return object_->data.cue_sheet.media_catalog_number;
  758. }
  759. FLAC__uint64 CueSheet::get_lead_in() const
  760. {
  761. FLAC__ASSERT(is_valid());
  762. return object_->data.cue_sheet.lead_in;
  763. }
  764. bool CueSheet::get_is_cd() const
  765. {
  766. FLAC__ASSERT(is_valid());
  767. return object_->data.cue_sheet.is_cd? true : false;
  768. }
  769. unsigned CueSheet::get_num_tracks() const
  770. {
  771. FLAC__ASSERT(is_valid());
  772. return object_->data.cue_sheet.num_tracks;
  773. }
  774. CueSheet::Track CueSheet::get_track(unsigned i) const
  775. {
  776. FLAC__ASSERT(is_valid());
  777. FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
  778. return Track(object_->data.cue_sheet.tracks + i);
  779. }
  780. void CueSheet::set_media_catalog_number(const char value[128])
  781. {
  782. FLAC__ASSERT(is_valid());
  783. FLAC__ASSERT(0 != value);
  784. memcpy(object_->data.cue_sheet.media_catalog_number, value, 128);
  785. object_->data.cue_sheet.media_catalog_number[128] = '';
  786. }
  787. void CueSheet::set_lead_in(FLAC__uint64 value)
  788. {
  789. FLAC__ASSERT(is_valid());
  790. object_->data.cue_sheet.lead_in = value;
  791. }
  792. void CueSheet::set_is_cd(bool value)
  793. {
  794. FLAC__ASSERT(is_valid());
  795. object_->data.cue_sheet.is_cd = value;
  796. }
  797. void CueSheet::set_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index)
  798. {
  799. FLAC__ASSERT(is_valid());
  800. FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
  801. FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices);
  802. object_->data.cue_sheet.tracks[track_num].indices[index_num] = index;
  803. }
  804. bool CueSheet::insert_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index)
  805. {
  806. FLAC__ASSERT(is_valid());
  807. FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
  808. FLAC__ASSERT(index_num <= object_->data.cue_sheet.tracks[track_num].num_indices);
  809. return (bool)::FLAC__metadata_object_cuesheet_track_insert_index(object_, track_num, index_num, index);
  810. }
  811. bool CueSheet::delete_index(unsigned track_num, unsigned index_num)
  812. {
  813. FLAC__ASSERT(is_valid());
  814. FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
  815. FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices);
  816. return (bool)::FLAC__metadata_object_cuesheet_track_delete_index(object_, track_num, index_num);
  817. }
  818. bool CueSheet::set_track(unsigned i, const CueSheet::Track &track)
  819. {
  820. FLAC__ASSERT(is_valid());
  821. FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
  822. // We can safely const_cast since copy=true
  823. return (bool)::FLAC__metadata_object_cuesheet_set_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true);
  824. }
  825. bool CueSheet::insert_track(unsigned i, const CueSheet::Track &track)
  826. {
  827. FLAC__ASSERT(is_valid());
  828. FLAC__ASSERT(i <= object_->data.cue_sheet.num_tracks);
  829. // We can safely const_cast since copy=true
  830. return (bool)::FLAC__metadata_object_cuesheet_insert_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true);
  831. }
  832. bool CueSheet::delete_track(unsigned i)
  833. {
  834. FLAC__ASSERT(is_valid());
  835. FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
  836. return (bool)::FLAC__metadata_object_cuesheet_delete_track(object_, i);
  837. }
  838. bool CueSheet::is_legal(bool check_cd_da_subset, const char **violation) const
  839. {
  840. FLAC__ASSERT(is_valid());
  841. return (bool)::FLAC__metadata_object_cuesheet_is_legal(object_, check_cd_da_subset, violation);
  842. }
  843. //
  844. // Unknown
  845. //
  846. Unknown::Unknown():
  847. Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
  848. { }
  849. Unknown::~Unknown()
  850. { }
  851. const FLAC__byte *Unknown::get_data() const
  852. {
  853. FLAC__ASSERT(is_valid());
  854. return object_->data.application.data;
  855. }
  856. bool Unknown::set_data(const FLAC__byte *data, unsigned length)
  857. {
  858. FLAC__ASSERT(is_valid());
  859. return (bool)::FLAC__metadata_object_application_set_data(object_, (FLAC__byte*)data, length, true);
  860. }
  861. bool Unknown::set_data(FLAC__byte *data, unsigned length, bool copy)
  862. {
  863. FLAC__ASSERT(is_valid());
  864. return (bool)::FLAC__metadata_object_application_set_data(object_, data, length, copy);
  865. }
  866. // ============================================================
  867. //
  868. //  Level 0
  869. //
  870. // ============================================================
  871. FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo)
  872. {
  873. FLAC__ASSERT(0 != filename);
  874. ::FLAC__StreamMetadata object;
  875. if(::FLAC__metadata_get_streaminfo(filename, &object)) {
  876. streaminfo = object;
  877. return true;
  878. }
  879. else
  880. return false;
  881. }
  882. FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags)
  883. {
  884. FLAC__ASSERT(0 != filename);
  885. ::FLAC__StreamMetadata *object;
  886. tags = 0;
  887. if(::FLAC__metadata_get_tags(filename, &object)) {
  888. tags = new VorbisComment(object, /*copy=*/false);
  889. return true;
  890. }
  891. else
  892. return false;
  893. }
  894. FLACPP_API bool get_tags(const char *filename, VorbisComment &tags)
  895. {
  896. FLAC__ASSERT(0 != filename);
  897. ::FLAC__StreamMetadata *object;
  898. if(::FLAC__metadata_get_tags(filename, &object)) {
  899. tags.assign(object, /*copy=*/false);
  900. return true;
  901. }
  902. else
  903. return false;
  904. }
  905. // ============================================================
  906. //
  907. //  Level 1
  908. //
  909. // ============================================================
  910. SimpleIterator::SimpleIterator():
  911. iterator_(::FLAC__metadata_simple_iterator_new())
  912. { }
  913. SimpleIterator::~SimpleIterator()
  914. {
  915. clear();
  916. }
  917. void SimpleIterator::clear()
  918. {
  919. if(0 != iterator_)
  920. FLAC__metadata_simple_iterator_delete(iterator_);
  921. iterator_ = 0;
  922. }
  923. bool SimpleIterator::init(const char *filename, bool read_only, bool preserve_file_stats)
  924. {
  925. FLAC__ASSERT(0 != filename);
  926. FLAC__ASSERT(is_valid());
  927. return (bool)::FLAC__metadata_simple_iterator_init(iterator_, filename, read_only, preserve_file_stats);
  928. }
  929. bool SimpleIterator::is_valid() const
  930. {
  931. return 0 != iterator_;
  932. }
  933. SimpleIterator::Status SimpleIterator::status()
  934. {
  935. FLAC__ASSERT(is_valid());
  936. return Status(::FLAC__metadata_simple_iterator_status(iterator_));
  937. }
  938. bool SimpleIterator::is_writable() const
  939. {
  940. FLAC__ASSERT(is_valid());
  941. return (bool)::FLAC__metadata_simple_iterator_is_writable(iterator_);
  942. }
  943. bool SimpleIterator::next()
  944. {
  945. FLAC__ASSERT(is_valid());
  946. return (bool)::FLAC__metadata_simple_iterator_next(iterator_);
  947. }
  948. bool SimpleIterator::prev()
  949. {
  950. FLAC__ASSERT(is_valid());
  951. return (bool)::FLAC__metadata_simple_iterator_prev(iterator_);
  952. }
  953. ::FLAC__MetadataType SimpleIterator::get_block_type() const
  954. {
  955. FLAC__ASSERT(is_valid());
  956. return ::FLAC__metadata_simple_iterator_get_block_type(iterator_);
  957. }
  958. Prototype *SimpleIterator::get_block()
  959. {
  960. FLAC__ASSERT(is_valid());
  961. return local::construct_block(::FLAC__metadata_simple_iterator_get_block(iterator_));
  962. }
  963. bool SimpleIterator::set_block(Prototype *block, bool use_padding)
  964. {
  965. FLAC__ASSERT(0 != block);
  966. FLAC__ASSERT(is_valid());
  967. return (bool)::FLAC__metadata_simple_iterator_set_block(iterator_, block->object_, use_padding);
  968. }
  969. bool SimpleIterator::insert_block_after(Prototype *block, bool use_padding)
  970. {
  971. FLAC__ASSERT(0 != block);
  972. FLAC__ASSERT(is_valid());
  973. return (bool)::FLAC__metadata_simple_iterator_insert_block_after(iterator_, block->object_, use_padding);
  974. }
  975. bool SimpleIterator::delete_block(bool use_padding)
  976. {
  977. FLAC__ASSERT(is_valid());
  978. return (bool)::FLAC__metadata_simple_iterator_delete_block(iterator_, use_padding);
  979. }
  980. // ============================================================
  981. //
  982. //  Level 2
  983. //
  984. // ============================================================
  985. Chain::Chain():
  986. chain_(::FLAC__metadata_chain_new())
  987. { }
  988. Chain::~Chain()
  989. {
  990. clear();
  991. }
  992. void Chain::clear()
  993. {
  994. if(0 != chain_)
  995. FLAC__metadata_chain_delete(chain_);
  996. chain_ = 0;
  997. }
  998. bool Chain::is_valid() const
  999. {
  1000. return 0 != chain_;
  1001. }
  1002. Chain::Status Chain::status()
  1003. {
  1004. FLAC__ASSERT(is_valid());
  1005. return Status(::FLAC__metadata_chain_status(chain_));
  1006. }
  1007. bool Chain::read(const char *filename)
  1008. {
  1009. FLAC__ASSERT(0 != filename);
  1010. FLAC__ASSERT(is_valid());
  1011. return (bool)::FLAC__metadata_chain_read(chain_, filename);
  1012. }
  1013. bool Chain::read(FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks)
  1014. {
  1015. FLAC__ASSERT(is_valid());
  1016. return (bool)::FLAC__metadata_chain_read_with_callbacks(chain_, handle, callbacks);
  1017. }
  1018. bool Chain::check_if_tempfile_needed(bool use_padding)
  1019. {
  1020. FLAC__ASSERT(is_valid());
  1021. return (bool)::FLAC__metadata_chain_check_if_tempfile_needed(chain_, use_padding);
  1022. }
  1023. bool Chain::write(bool use_padding, bool preserve_file_stats)
  1024. {
  1025. FLAC__ASSERT(is_valid());
  1026. return (bool)::FLAC__metadata_chain_write(chain_, use_padding, preserve_file_stats);
  1027. }
  1028. bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks)
  1029. {
  1030. FLAC__ASSERT(is_valid());
  1031. return (bool)::FLAC__metadata_chain_write_with_callbacks(chain_, use_padding, handle, callbacks);
  1032. }
  1033. bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks)
  1034. {
  1035. FLAC__ASSERT(is_valid());
  1036. return (bool)::FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain_, use_padding, handle, callbacks, temp_handle, temp_callbacks);
  1037. }
  1038. void Chain::merge_padding()
  1039. {
  1040. FLAC__ASSERT(is_valid());
  1041. ::FLAC__metadata_chain_merge_padding(chain_);
  1042. }
  1043. void Chain::sort_padding()
  1044. {
  1045. FLAC__ASSERT(is_valid());
  1046. ::FLAC__metadata_chain_sort_padding(chain_);
  1047. }
  1048. Iterator::Iterator():
  1049. iterator_(::FLAC__metadata_iterator_new())
  1050. { }
  1051. Iterator::~Iterator()
  1052. {
  1053. clear();
  1054. }
  1055. void Iterator::clear()
  1056. {
  1057. if(0 != iterator_)
  1058. FLAC__metadata_iterator_delete(iterator_);
  1059. iterator_ = 0;
  1060. }
  1061. bool Iterator::is_valid() const
  1062. {
  1063. return 0 != iterator_;
  1064. }
  1065. void Iterator::init(Chain &chain)
  1066. {
  1067. FLAC__ASSERT(is_valid());
  1068. FLAC__ASSERT(chain.is_valid());
  1069. ::FLAC__metadata_iterator_init(iterator_, chain.chain_);
  1070. }
  1071. bool Iterator::next()
  1072. {
  1073. FLAC__ASSERT(is_valid());
  1074. return (bool)::FLAC__metadata_iterator_next(iterator_);
  1075. }
  1076. bool Iterator::prev()
  1077. {
  1078. FLAC__ASSERT(is_valid());
  1079. return (bool)::FLAC__metadata_iterator_prev(iterator_);
  1080. }
  1081. ::FLAC__MetadataType Iterator::get_block_type() const
  1082. {
  1083. FLAC__ASSERT(is_valid());
  1084. return ::FLAC__metadata_iterator_get_block_type(iterator_);
  1085. }
  1086. Prototype *Iterator::get_block()
  1087. {
  1088. FLAC__ASSERT(is_valid());
  1089. Prototype *block = local::construct_block(::FLAC__metadata_iterator_get_block(iterator_));
  1090. if(0 != block)
  1091. block->set_reference(true);
  1092. return block;
  1093. }
  1094. bool Iterator::set_block(Prototype *block)
  1095. {
  1096. FLAC__ASSERT(0 != block);
  1097. FLAC__ASSERT(is_valid());
  1098. bool ret = (bool)::FLAC__metadata_iterator_set_block(iterator_, block->object_);
  1099. if(ret) {
  1100. block->set_reference(true);
  1101. delete block;
  1102. }
  1103. return ret;
  1104. }
  1105. bool Iterator::delete_block(bool replace_with_padding)
  1106. {
  1107. FLAC__ASSERT(is_valid());
  1108. return (bool)::FLAC__metadata_iterator_delete_block(iterator_, replace_with_padding);
  1109. }
  1110. bool Iterator::insert_block_before(Prototype *block)
  1111. {
  1112. FLAC__ASSERT(0 != block);
  1113. FLAC__ASSERT(is_valid());
  1114. bool ret = (bool)::FLAC__metadata_iterator_insert_block_before(iterator_, block->object_);
  1115. if(ret) {
  1116. block->set_reference(true);
  1117. delete block;
  1118. }
  1119. return ret;
  1120. }
  1121. bool Iterator::insert_block_after(Prototype *block)
  1122. {
  1123. FLAC__ASSERT(0 != block);
  1124. FLAC__ASSERT(is_valid());
  1125. bool ret = (bool)::FLAC__metadata_iterator_insert_block_after(iterator_, block->object_);
  1126. if(ret) {
  1127. block->set_reference(true);
  1128. delete block;
  1129. }
  1130. return ret;
  1131. }
  1132. }
  1133. }