ym2149_common/metadata.rs
1//! Unified playback metadata trait.
2//!
3//! This module provides a common interface for metadata across different
4//! chiptune file formats (YM, AKS, AY).
5
6/// Unified metadata trait for chiptune playback.
7///
8/// Implementations of this trait provide a common interface to access
9/// song metadata regardless of the underlying file format.
10pub trait MetadataFields {
11 /// Get the song title.
12 fn title(&self) -> &str;
13
14 /// Get the author/composer name.
15 fn author(&self) -> &str;
16
17 /// Get additional comments or description.
18 ///
19 /// Returns an empty string if no comments are available.
20 fn comments(&self) -> &str {
21 ""
22 }
23
24 /// Get the file format identifier.
25 ///
26 /// Examples: "YM6", "AKS", "AY"
27 fn format(&self) -> &str;
28
29 /// Get the total frame count, if known.
30 fn frame_count(&self) -> Option<usize> {
31 None
32 }
33
34 /// Get the playback frame rate in Hz.
35 ///
36 /// Typical values: 50 (PAL) or 60 (NTSC).
37 fn frame_rate(&self) -> u32 {
38 50
39 }
40
41 /// Get the song duration in seconds, if known.
42 fn duration_seconds(&self) -> Option<f32> {
43 self.frame_count()
44 .map(|fc| fc as f32 / self.frame_rate() as f32)
45 }
46
47 /// Get the loop start frame, if the song loops.
48 fn loop_frame(&self) -> Option<usize> {
49 None
50 }
51}
52
53/// Unified metadata trait for chiptune playback.
54///
55/// This is a thin marker over [`MetadataFields`], provided for compatibility
56/// with the existing public API.
57pub trait PlaybackMetadata: MetadataFields {}
58
59impl<T: MetadataFields> PlaybackMetadata for T {}
60
61/// Basic metadata container implementing `PlaybackMetadata`.
62///
63/// This is a simple struct that can be used when you need to store
64/// metadata without the original parser structures.
65#[derive(Debug, Clone, Default, PartialEq, Eq)]
66pub struct BasicMetadata {
67 /// Song title.
68 pub title: String,
69 /// Author/composer name.
70 pub author: String,
71 /// Additional comments.
72 pub comments: String,
73 /// File format identifier (e.g., "YM6", "AKS").
74 pub format: String,
75 /// Total frame count.
76 pub frame_count: Option<usize>,
77 /// Playback frame rate in Hz.
78 pub frame_rate: u32,
79 /// Loop start frame.
80 pub loop_frame: Option<usize>,
81}
82
83impl MetadataFields for BasicMetadata {
84 fn title(&self) -> &str {
85 &self.title
86 }
87
88 fn author(&self) -> &str {
89 &self.author
90 }
91
92 fn comments(&self) -> &str {
93 &self.comments
94 }
95
96 fn format(&self) -> &str {
97 &self.format
98 }
99
100 fn frame_count(&self) -> Option<usize> {
101 self.frame_count
102 }
103
104 fn frame_rate(&self) -> u32 {
105 self.frame_rate
106 }
107
108 fn loop_frame(&self) -> Option<usize> {
109 self.loop_frame
110 }
111}
112
113impl BasicMetadata {
114 /// Create a new `BasicMetadata` with default values.
115 pub fn new() -> Self {
116 Self {
117 frame_rate: 50,
118 ..Default::default()
119 }
120 }
121
122 /// Create metadata from title and author.
123 pub fn with_title_author(title: impl Into<String>, author: impl Into<String>) -> Self {
124 Self {
125 title: title.into(),
126 author: author.into(),
127 frame_rate: 50,
128 ..Default::default()
129 }
130 }
131}