Skip to content

Commit f69c4d5

Browse files
committed
EBML: Add more generic tag mappings
1 parent e6976f5 commit f69c4d5

File tree

8 files changed

+115
-47
lines changed

8 files changed

+115
-47
lines changed

lofty/src/ebml/tag/generic.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,28 @@ macro_rules! matroska_mapping_tables {
5656

5757
matroska_mapping_tables!(
5858
Shot => [];
59-
Scene => [];
59+
Scene => [
60+
// Identifiers
61+
"TITLE" <=> Movement,
62+
"PART_NUMBER" <=> MovementNumber,
63+
"TOTAL_PARTS" <=> MovementTotal,
64+
];
6065
Track => [
6166
// Organization Information
6267
"PART_NUMBER" <=> TrackNumber,
6368

6469
// Titles
70+
// TODO: This should be T=50 for MKV
6571
"TITLE" <=> TrackTitle,
72+
// TODO: This should be T=50 for MKV
6673
"SUBTITLE" <=> TrackSubtitle,
6774

6875
// Nested Information
76+
// TODO: This should be T=50 for MKV
6977
"SORT_WITH" <=> TrackTitleSortOrder,
7078

7179
// Entities
80+
// TODO: This should be T=50 for MKV
7281
"ARTIST" <=> TrackArtist,
7382
"LYRICS" <=> Lyrics,
7483
"COMPOSER" <=> Composer,
@@ -77,6 +86,7 @@ matroska_mapping_tables!(
7786
"CONDUCTOR" <=> Conductor,
7887
"DIRECTOR" <=> Director,
7988
"PRODUCER" <=> Producer,
89+
// TODO: This should be T=50 for MKV
8090
"ENCODED_BY" <=> EncodedBy,
8191
"MIXED_BY" <=> MixDj,
8292
"REMIXED_BY" <=> Remixer,
@@ -89,12 +99,45 @@ matroska_mapping_tables!(
8999
"INITIAL_KEY" <=> InitialKey,
90100
"ORIGINAL_MEDIA_TYPE" <=> OriginalMediaType,
91101

102+
// Flags
103+
"COMPILATION" <=> FlagCompilation,
104+
"PODCAST" <=> FlagPodcast,
105+
106+
// File Information
107+
"FILETYPE" <=> FileType,
108+
// TODO: Should be T=50 for MKV
109+
"PURCHASE_OWNER" <=> FileOwner,
110+
"TAGGINGTIME" <=> TaggingTime,
111+
"LENGTH" <=> Length,
112+
"ORIGFILENAME" <=> OriginalFileName,
113+
"ORIGINAL_MEDIA_TYPE" <=> OriginalMediaType,
114+
115+
// URLs
116+
"WWWAUDIOFILE" <=> AudioFileUrl,
117+
"WWWAUDIOSOURCE" <=> AudioSourceUrl,
118+
// TODO: Should be T=50 for MKV
119+
"PURCHASE_INFO" <=> CommercialInformationUrl,
120+
"WWWCOPYRIGHT" <=> CopyrightUrl,
121+
"WWWARTIST" <=> TrackArtistUrl,
122+
"WWWRADIOPAGE" <=> RadioStationUrl,
123+
// TODO: Should be T=50 for MKV
124+
"PURCHASE_ITEM" <=> PaymentUrl,
125+
"WWWPUBLISHER" <=> PublisherUrl,
126+
92127
// Technical Information
93128
"ENCODER" <=> EncoderSoftware,
129+
// TODO: This should be T=50 for MKV
94130
"ENCODER_SETTINGS" <=> EncoderSettings,
95131
"BPM" <=> Bpm,
96132
// TODO: ReplayGain? The values are binary in Matroska
97133

134+
// Podcast
135+
"PODCASTDESC" <=> PodcastDescription,
136+
"PODCASTCATEGORY" <=> PodcastSeriesCategory,
137+
"PODCASTURL" <=> PodcastUrl,
138+
"PODCASTID" <=> PodcastGlobalUniqueId,
139+
"PODCASTKEYWORDS" <=> PodcastKeywords,
140+
98141
// Identifiers
99142
"ISRC" <=> Isrc,
100143
"BARCODE" <=> Barcode,
@@ -106,12 +149,17 @@ matroska_mapping_tables!(
106149
"TOTAL_PARTS" <=> TrackTotal,
107150

108151
// Titles
152+
// TODO: This should be T=60 for MKV
109153
"TITLE" <=> AlbumTitle,
154+
// TODO: This should be T=60 for MKV
155+
"SUBTITLE" <=> SetSubtitle,
110156

111157
// Nested Information
158+
// TODO: This should be T=60 for MKV
112159
"SORT_WITH" <=> AlbumTitleSortOrder,
113160

114161
// Entities
162+
// TODO: This should be T=60 for MKV
115163
"ARTIST" <=> AlbumArtist,
116164

117165
// Temporal Information

lofty/src/ebml/tag/mod.rs

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ pub use tag_name::*;
1616
pub use target::*;
1717

1818
use crate::config::{WriteOptions, global_options};
19+
use crate::ebml::tag::write::{ElementWriterCtx, WriteableElement};
1920
use crate::error::{LoftyError, Result};
2021
use crate::io::{FileLike, Length, Truncate};
2122
use crate::picture::Picture;
2223
use crate::tag::companion_tag::CompanionTag;
2324
use crate::tag::{Accessor, MergeTag, SplitTag, TagExt, TagType};
24-
use crate::ebml::tag::write::{ElementWriterCtx, WriteableElement};
2525

2626
use std::borrow::Cow;
2727
use std::collections::HashMap;
@@ -35,7 +35,7 @@ macro_rules! impl_accessor {
3535
paste::paste! {
3636
$(
3737
fn $method(&self) -> Option<Cow<'_, str>> {
38-
self.get_str(MatroskaTagKey(TargetType::$target, $name.into()))
38+
self.get_str(TargetType::$target, $name)
3939
}
4040

4141
fn [<set_ $method>](&mut self, value: String) {
@@ -72,8 +72,11 @@ pub struct MatroskaTag {
7272
pub struct MatroskaTagKey<'a>(TargetType, Cow<'a, str>);
7373

7474
impl MatroskaTag {
75-
fn get(&self, key: MatroskaTagKey<'_>) -> Option<&SimpleTag<'_>> {
76-
let MatroskaTagKey(target, key) = key;
75+
fn get<'a, K>(&self, target: TargetType, key: K) -> Option<&SimpleTag<'_>>
76+
where
77+
K: Into<Cow<'a, str>>,
78+
{
79+
let key = key.into();
7780

7881
let applicable_tags = self.tags.iter().filter(|tag| tag.matches_target(target));
7982
for applicable_tag in applicable_tags {
@@ -112,8 +115,11 @@ impl MatroskaTag {
112115
self.tags.get_mut(pos.unwrap()).unwrap()
113116
}
114117

115-
fn get_str(&self, key: MatroskaTagKey<'_>) -> Option<Cow<'_, str>> {
116-
let simple_tag = self.get(key)?;
118+
fn get_str<'a, K>(&self, target: TargetType, key: K) -> Option<Cow<'_, str>>
119+
where
120+
K: Into<Cow<'a, str>>,
121+
{
122+
let simple_tag = self.get(target, key)?;
117123
simple_tag.get_str().map(Cow::from)
118124
}
119125

@@ -279,39 +285,60 @@ impl Accessor for MatroskaTag {
279285
);
280286

281287
fn track(&self) -> Option<u32> {
282-
self.get(MatroskaTagKey(
283-
TargetType::Track,
284-
Cow::Borrowed("PART_NUMBER"),
285-
))
286-
.and_then(SimpleTag::get_str)
287-
.and_then(|val| val.parse::<u32>().ok())
288+
self.get_str(TargetType::Track, TagName::PartNumber)
289+
.and_then(|val| val.parse::<u32>().ok())
288290
}
289291

290-
fn set_track(&mut self, _value: u32) {
291-
todo!()
292+
fn set_track(&mut self, value: u32) {
293+
let tag = SimpleTag::new(TagName::PartNumber, value.to_string());
294+
self.push(TargetType::Track, tag);
292295
}
293296

294297
fn remove_track(&mut self) {
295298
todo!()
296299
}
297300

298301
fn track_total(&self) -> Option<u32> {
299-
self.get(MatroskaTagKey(
300-
TargetType::Album,
301-
Cow::Borrowed("TOTAL_PARTS"),
302-
))
303-
.and_then(SimpleTag::get_str)
304-
.and_then(|val| val.parse::<u32>().ok())
302+
self.get(TargetType::Album, TagName::TotalParts)
303+
.and_then(SimpleTag::get_str)
304+
.and_then(|val| val.parse::<u32>().ok())
305305
}
306306

307-
fn set_track_total(&mut self, _value: u32) {
308-
todo!()
307+
fn set_track_total(&mut self, value: u32) {
308+
let tag = SimpleTag::new(TagName::TotalParts, value.to_string());
309+
self.push(TargetType::Album, tag);
309310
}
310311

311312
fn remove_track_total(&mut self) {
312313
todo!()
313314
}
314315

316+
fn disk(&self) -> Option<u32> {
317+
self.get(TargetType::Edition, TagName::PartNumber)
318+
.and_then(SimpleTag::get_str)
319+
.and_then(|val| val.parse::<u32>().ok())
320+
}
321+
322+
fn set_disk(&mut self, value: u32) {
323+
let tag = SimpleTag::new(TagName::PartNumber, value.to_string());
324+
self.push(TargetType::Edition, tag);
325+
}
326+
327+
fn remove_disk(&mut self) {}
328+
329+
fn disk_total(&self) -> Option<u32> {
330+
self.get(TargetType::Edition, TagName::TotalParts)
331+
.and_then(SimpleTag::get_str)
332+
.and_then(|val| val.parse::<u32>().ok())
333+
}
334+
335+
fn set_disk_total(&mut self, value: u32) {
336+
let tag = SimpleTag::new(TagName::TotalParts, value.to_string());
337+
self.push(TargetType::Edition, tag);
338+
}
339+
340+
fn remove_disk_total(&mut self) {}
341+
315342
fn year(&self) -> Option<u32> {
316343
// `DATE_RELEASED`
317344
todo!()
@@ -441,15 +468,14 @@ impl From<crate::tag::Tag> for MatroskaTag {
441468
}
442469
}
443470

444-
pub(crate) struct MatroskaTagRef<'a>
445-
{
471+
pub(crate) struct MatroskaTagRef<'a> {
446472
pub(crate) tags: Vec<TagRef<'a>>,
447473
}
448474

449475
impl<'a> From<&'a MatroskaTag> for MatroskaTagRef<'a> {
450476
fn from(value: &'a MatroskaTag) -> Self {
451477
Self {
452-
tags: value.tags.iter().map(Into::into).collect::<Vec<_>>()
478+
tags: value.tags.iter().map(Into::into).collect::<Vec<_>>(),
453479
}
454480
}
455481
}
@@ -459,7 +485,9 @@ impl<'a> From<&'a crate::tag::Tag> for MatroskaTagRef<'static> {
459485
let mut mapped_tags: HashMap<TargetType, Vec<Cow<'static, SimpleTag<'static>>>> =
460486
HashMap::new();
461487
for item in &value.items {
462-
if let Some((simple_tag, target_type)) = generic::simple_tag_for_item(Cow::Borrowed(item)) {
488+
if let Some((simple_tag, target_type)) =
489+
generic::simple_tag_for_item(Cow::Borrowed(item))
490+
{
463491
mapped_tags
464492
.entry(target_type)
465493
.or_default()
@@ -472,16 +500,14 @@ impl<'a> From<&'a crate::tag::Tag> for MatroskaTagRef<'static> {
472500
.map(|(target_type, simple_tags)| TagRef {
473501
targets: TargetDescriptor::Basic(target_type),
474502
simple_tags,
475-
}).collect::<Vec<_>>();
503+
})
504+
.collect::<Vec<_>>();
476505

477-
Self {
478-
tags
479-
}
506+
Self { tags }
480507
}
481508
}
482509

483-
impl<'a> MatroskaTagRef<'a>
484-
{
510+
impl<'a> MatroskaTagRef<'a> {
485511
pub(crate) fn write_to<F>(&mut self, file: &mut F, write_options: WriteOptions) -> Result<()>
486512
where
487513
F: FileLike,

lofty/src/ebml/tag/write/elements/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
pub(super) mod attached_file;
44
pub(super) mod simple_tag;
5+
mod tag;
56
pub(super) mod tags;
67
pub(super) mod target;
7-
mod tag;

lofty/src/ebml/tag/write/elements/tag.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ impl WriteableElement for TagRef<'_> {
2929

3030
Ok(())
3131
}
32-
}
32+
}

lofty/src/ebml/tag/write/elements/tags.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use crate::ebml::tag::write::{write_element, ElementWriterCtx, WriteableElement};
1+
use crate::ebml::tag::write::{ElementWriterCtx, WriteableElement, write_element};
22
use crate::ebml::{ElementId, MatroskaTagRef};
33
use crate::io::FileLike;
44

55
use std::io::Cursor;
66

77
// Segment\Tags
8-
impl<'a> WriteableElement for MatroskaTagRef<'a>
9-
{
8+
impl<'a> WriteableElement for MatroskaTagRef<'a> {
109
const ID: ElementId = ElementId(0x1254_C367);
1110

1211
fn write_element<F: FileLike>(

lofty/src/ebml/tag/write/elements/target.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,7 @@ mod tests {
9393
let mut buf = Cursor::new(Vec::new());
9494
let target_descriptor = TargetDescriptor::from(&target);
9595
target_descriptor
96-
.write_element(
97-
ElementWriterCtx::default(),
98-
&mut buf,
99-
)
96+
.write_element(ElementWriterCtx::default(), &mut buf)
10097
.unwrap();
10198

10299
let expected = vec![0x63, 0xC0, 0x80];

lofty/src/ebml/tag/write/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
mod elements;
22
mod type_encodings;
33

4-
use crate::ebml::{ElementId, VInt};
5-
use crate::error::Result;
64
use super::MatroskaTagRef;
75
use crate::config::WriteOptions;
8-
use crate::error::LoftyError;
6+
use crate::ebml::{ElementId, VInt};
7+
use crate::error::{LoftyError, Result};
98
use crate::io::{FileLike, Truncate};
109

1110
use std::io::Write;

lofty/src/tag/utils.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ pub(crate) fn dump_tag<W: Write>(
9999
}
100100
}
101101
.dump_to(writer, write_options),
102-
TagType::Matroska => ebml::tag::MatroskaTagRef::from(tag)
103-
.dump_to(writer, write_options),
102+
TagType::Matroska => ebml::tag::MatroskaTagRef::from(tag).dump_to(writer, write_options),
104103
_ => Ok(()),
105104
}
106105
}

0 commit comments

Comments
 (0)