This commit is contained in:
Tianyi 2020-10-27 20:26:59 +00:00
parent 5808028494
commit ff2e0c6959
19 changed files with 990 additions and 26 deletions

1
.gitignore vendored
View file

@ -20,3 +20,4 @@ rtfm/.Rproj.user
rtfm/.Rhistory rtfm/.Rhistory
rtfm/.RData rtfm/.RData
rtfm/.Ruserdata rtfm/.Ruserdata
.Rproj.user

View file

@ -4,6 +4,7 @@
[![Crate](https://img.shields.io/crates/d/audiotags.svg)](https://crates.io/crates/audiotags) [![Crate](https://img.shields.io/crates/d/audiotags.svg)](https://crates.io/crates/audiotags)
[![Crate](https://img.shields.io/crates/l/audiotags.svg)](https://crates.io/crates/audiotags) [![Crate](https://img.shields.io/crates/l/audiotags.svg)](https://crates.io/crates/audiotags)
[![Documentation](https://docs.rs/audiotags/badge.svg)](https://docs.rs/audiotags/) [![Documentation](https://docs.rs/audiotags/badge.svg)](https://docs.rs/audiotags/)
[![Manual](https://img.shields.io/badge/RTFM-Manual-blue)](https://tianyishi2001.github.io/audiotags)
This crate makes it easier to parse, convert and write metadata (a.k.a tag) in audio files of different file types. This crate makes it easier to parse, convert and write metadata (a.k.a tag) in audio files of different file types.

238
docs/anytag.html Normal file
View file

@ -0,0 +1,238 @@
<!DOCTYPE html>
<html lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Chapter 3 AnyTag | audiotags Manual</title>
<meta name="description" content="This is the manual of the Rust crate audiotags" />
<meta name="generator" content="bookdown 0.21 and GitBook 2.6.7" />
<meta property="og:title" content="Chapter 3 AnyTag | audiotags Manual" />
<meta property="og:type" content="book" />
<meta property="og:description" content="This is the manual of the Rust crate audiotags" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Chapter 3 AnyTag | audiotags Manual" />
<meta name="twitter:description" content="This is the manual of the Rust crate audiotags" />
<meta name="author" content="Tianyi Shi" />
<meta name="date" content="2020-10-27" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="prev" href="conversion.html"/>
<link rel="next" href="downcast.html"/>
<script src="libs/header-attrs-2.4/header-attrs.js"></script>
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-clipboard.css" rel="stylesheet" />
<style type="text/css">
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">
<div class="book-summary">
<nav role="navigation">
<ul class="summary">
<li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li>
<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
</ul></li>
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
<li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
<li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i><a href="./">audiotags Manual</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<section class="normal" id="section-">
<div id="anytag" class="section level1" number="3">
<h1><span class="header-section-number">Chapter 3</span> <code>AnyTag</code></h1>
<p>The following example shows how you can create a “generic” <code>AnyTag</code> and convert it into a specific tag type.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="anytag.html#cb3-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span>AnyTag<span class="op">,</span> AudioTagEdit<span class="op">,</span> Id3v2Tag<span class="op">};</span></span>
<span id="cb3-2"><a href="anytag.html#cb3-2" aria-hidden="true"></a></span>
<span id="cb3-3"><a href="anytag.html#cb3-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb3-4"><a href="anytag.html#cb3-4" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">AnyTag::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb3-5"><a href="anytag.html#cb3-5" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">&quot;foo&quot;</span>)<span class="op">;</span></span>
<span id="cb3-6"><a href="anytag.html#cb3-6" aria-hidden="true"></a> tag<span class="op">.</span>set_year(<span class="dv">2001</span>)<span class="op">;</span></span>
<span id="cb3-7"><a href="anytag.html#cb3-7" aria-hidden="true"></a> <span class="kw">let</span> tag<span class="op">:</span> Id3v2Tag <span class="op">=</span> tag<span class="op">.</span>into()<span class="op">;</span></span>
<span id="cb3-8"><a href="anytag.html#cb3-8" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>year()<span class="op">,</span> <span class="cn">Some</span>(<span class="dv">2001</span>))<span class="op">;</span></span>
<span id="cb3-9"><a href="anytag.html#cb3-9" aria-hidden="true"></a> tag<span class="op">.</span>write_to_path(<span class="st">&quot;assets/a.mp3&quot;</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
<span id="cb3-10"><a href="anytag.html#cb3-10" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
</div>
</section>
</div>
</div>
</div>
<a href="conversion.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="downcast.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
</div>
</div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
<script src="libs/gitbook-2.6.7/js/clipboard.min.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-clipboard.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": false,
"facebook": true,
"twitter": true,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"all": ["facebook", "twitter", "linkedin", "weibo", "instapaper"]
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": null,
"text": null
},
"history": {
"link": null,
"text": null
},
"view": {
"link": null,
"text": null
},
"download": ["audiotags.pdf", "audiotags.epub"],
"toc": {
"collapse": "subsection"
}
});
});
</script>
</body>
</html>

Binary file not shown.

Binary file not shown.

View file

@ -131,6 +131,23 @@
Thank you for considering \textbf{audiotags}! Thank you for considering \textbf{audiotags}!
\hypertarget{examples-in-this-manual}{%
\subsection*{Examples in this manual}\label{examples-in-this-manual}}
\addcontentsline{toc}{subsection}{Examples in this manual}
If you want to run the examples in this book:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\tightlist
\item
clone the \href{https://github.com/TianyiShi2001/audiotags}{repo} and navigate into it
\item
create \texttt{src/main.rs}
\item
all examples, unless otherwise specified, can be copied verbatim from this book to \texttt{src/main.rs} and run with \texttt{cargo\ run} (if you're reading it online, the copy button wil show if you hover over a code block)
\end{enumerate}
\hypertarget{start-simple}{% \hypertarget{start-simple}{%
\chapter{Start Simple}\label{start-simple}} \chapter{Start Simple}\label{start-simple}}
@ -175,10 +192,114 @@ The following example shows how you can read an audio file, parse, set, and save
\end{Highlighting} \end{Highlighting}
\end{Shaded} \end{Shaded}
\hypertarget{final-words}{% \hypertarget{conversion}{%
\chapter{Final Words}\label{final-words}} \chapter{Conversion}\label{conversion}}
The following example shows how you can read the tag in an \texttt{mp3} file, convert it into an \texttt{mp4} tag, and write it to an \texttt{m4a} file.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{\{}\NormalTok{Config}\OperatorTok{,}\NormalTok{ Tag}\OperatorTok{,}\NormalTok{ TagType}\OperatorTok{\};}
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
\CommentTok{// we have an mp3 and an m4a file}
\KeywordTok{const}\NormalTok{ MP3\_FILE}\OperatorTok{:} \OperatorTok{\&}\OtherTok{\textquotesingle{}static} \DataTypeTok{str} \OperatorTok{=} \StringTok{"assets/a.mp3"}\OperatorTok{;}
\KeywordTok{const}\NormalTok{ M4A\_FILE}\OperatorTok{:} \OperatorTok{\&}\OtherTok{\textquotesingle{}static} \DataTypeTok{str} \OperatorTok{=} \StringTok{"assets/a.m4a"}\OperatorTok{;}
\CommentTok{// read tag from the mp3 file. Using \textasciigrave{}default()\textasciigrave{} so that the type of tag is guessed from the file extension}
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ mp3tag }\OperatorTok{=} \PreprocessorTok{Tag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{.}\NormalTok{read\_from\_path(MP3\_FILE)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
\CommentTok{// set the title}
\NormalTok{ mp3tag}\OperatorTok{.}\NormalTok{set\_title(}\StringTok{"title from mp3 file"}\NormalTok{)}\OperatorTok{;}
\CommentTok{// we can convert it to an mp4 tag and save it to an m4a file.}
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ mp4tag }\OperatorTok{=}\NormalTok{ mp3tag}\OperatorTok{.}\NormalTok{into\_tag(}\PreprocessorTok{TagType::}\NormalTok{Mp4)}\OperatorTok{;}
\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{write\_to\_path(M4A\_FILE)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
\CommentTok{// reload the tag from the m4a file; this time specifying the tag type (you can also use \textasciigrave{}default()\textasciigrave{})}
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ mp4tag }\OperatorTok{=} \PreprocessorTok{Tag::}\NormalTok{with\_tag\_type(}\PreprocessorTok{TagType::}\NormalTok{Mp4)}
\OperatorTok{.}\NormalTok{read\_from\_path(M4A\_FILE)}
\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
\CommentTok{// the tag originated from an mp3 file is successfully written to an m4a file!}
\PreprocessorTok{assert\_eq!}\NormalTok{(mp4tag}\OperatorTok{.}\NormalTok{title()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"title from mp3 file"}\NormalTok{))}\OperatorTok{;}
\CommentTok{// multiple artists}
\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{add\_artist(}\StringTok{"artist1 of mp4"}\NormalTok{)}\OperatorTok{;}
\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{add\_artist(}\StringTok{"artist2 of mp4"}\NormalTok{)}\OperatorTok{;}
\PreprocessorTok{assert\_eq!}\NormalTok{(}
\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{artists()}\OperatorTok{,}
\ConstantTok{Some}\NormalTok{(}\PreprocessorTok{vec!}\NormalTok{[}\StringTok{"artist1 of mp4"}\OperatorTok{,} \StringTok{"artist2 of mp4"}\NormalTok{])}
\NormalTok{ )}\OperatorTok{;}
\CommentTok{// convert to id3 tag, which does not support multiple artists}
\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{set\_config(}\PreprocessorTok{Config::}\KeywordTok{default}\NormalTok{()}\OperatorTok{.}\NormalTok{sep\_artist(}\StringTok{"/"}\NormalTok{))}\OperatorTok{;}
\CommentTok{// separator is by default \textasciigrave{};\textasciigrave{} but we can customise it}
\KeywordTok{let}\NormalTok{ mp3tag }\OperatorTok{=}\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{into\_tag(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}\OperatorTok{;}
\PreprocessorTok{assert\_eq!}\NormalTok{(mp3tag}\OperatorTok{.}\NormalTok{artist()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"artist1 of mp4/artist2 of mp4"}\NormalTok{))}\OperatorTok{;}
\OperatorTok{\}}
\end{Highlighting}
\end{Shaded}
\hypertarget{anytag}{%
\chapter{\texorpdfstring{\texttt{AnyTag}}{AnyTag}}\label{anytag}}
The following example shows how you can create a ``generic'' \texttt{AnyTag} and convert it into a specific tag type.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{\{}\NormalTok{AnyTag}\OperatorTok{,}\NormalTok{ AudioTagEdit}\OperatorTok{,}\NormalTok{ Id3v2Tag}\OperatorTok{\};}
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ tag }\OperatorTok{=} \PreprocessorTok{AnyTag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{;}
\NormalTok{ tag}\OperatorTok{.}\NormalTok{set\_title(}\StringTok{"foo"}\NormalTok{)}\OperatorTok{;}
\NormalTok{ tag}\OperatorTok{.}\NormalTok{set\_year(}\DecValTok{2001}\NormalTok{)}\OperatorTok{;}
\KeywordTok{let}\NormalTok{ tag}\OperatorTok{:}\NormalTok{ Id3v2Tag }\OperatorTok{=}\NormalTok{ tag}\OperatorTok{.}\NormalTok{into()}\OperatorTok{;}
\PreprocessorTok{assert\_eq!}\NormalTok{(tag}\OperatorTok{.}\NormalTok{year()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\DecValTok{2001}\NormalTok{))}\OperatorTok{;}
\NormalTok{ tag}\OperatorTok{.}\NormalTok{write\_to\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
\OperatorTok{\}}
\end{Highlighting}
\end{Shaded}
\hypertarget{downcast}{%
\chapter{Downcast}\label{downcast}}
The following example shows how you can downcast a \texttt{Box\textless{}dyn\ AudioTag\textgreater{}} into its ``backend'' tag type. This allows you to set the uncommon metadata supported by the corresponding backend but not by \textbf{audiotags}.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{*;}
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ innertag }\OperatorTok{=} \PreprocessorTok{metaflac::Tag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{;}
\NormalTok{ innertag}
\OperatorTok{.}\NormalTok{vorbis\_comments\_mut()}
\OperatorTok{.}\NormalTok{set\_title(}\PreprocessorTok{vec!}\NormalTok{[}\StringTok{"title from metaflac::Tag"}\NormalTok{])}\OperatorTok{;}
\KeywordTok{let}\NormalTok{ tag}\OperatorTok{:}\NormalTok{ FlacTag }\OperatorTok{=}\NormalTok{ innertag}\OperatorTok{.}\NormalTok{into()}\OperatorTok{;}
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ id3tag }\OperatorTok{=}\NormalTok{ tag}\OperatorTok{.}\NormalTok{into\_tag(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}\OperatorTok{;}
\NormalTok{ id3tag}
\OperatorTok{.}\NormalTok{write\_to\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to write!"}\NormalTok{)}\OperatorTok{;}
\KeywordTok{let}\NormalTok{ id3tag\_reload }\OperatorTok{=} \PreprocessorTok{Tag::}\KeywordTok{default}\NormalTok{()}
\OperatorTok{.}\NormalTok{read\_from\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to read!"}\NormalTok{)}\OperatorTok{;}
\PreprocessorTok{assert\_eq!}\NormalTok{(id3tag\_reload}\OperatorTok{.}\NormalTok{title()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"title from metaflac::Tag"}\NormalTok{))}\OperatorTok{;}
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ id3tag\_inner}\OperatorTok{:} \PreprocessorTok{id3::}\NormalTok{Tag }\OperatorTok{=} \PreprocessorTok{downcast!}\NormalTok{(id3tag\_reload}\OperatorTok{,}\NormalTok{ Id3v2Tag)}\OperatorTok{;}
\KeywordTok{let}\NormalTok{ timestamp }\OperatorTok{=} \PreprocessorTok{id3::}\NormalTok{Timestamp }\OperatorTok{\{}
\NormalTok{ year}\OperatorTok{:} \DecValTok{2013}\OperatorTok{,}
\NormalTok{ month}\OperatorTok{:} \ConstantTok{Some}\NormalTok{(}\DecValTok{2u8}\NormalTok{)}\OperatorTok{,}
\NormalTok{ day}\OperatorTok{:} \ConstantTok{Some}\NormalTok{(}\DecValTok{5u8}\NormalTok{)}\OperatorTok{,}
\NormalTok{ hour}\OperatorTok{:} \ConstantTok{Some}\NormalTok{(}\DecValTok{6u8}\NormalTok{)}\OperatorTok{,}
\NormalTok{ minute}\OperatorTok{:} \ConstantTok{None}\OperatorTok{,}
\NormalTok{ second}\OperatorTok{:} \ConstantTok{None}\OperatorTok{,}
\OperatorTok{\};}
\NormalTok{ id3tag\_inner}\OperatorTok{.}\NormalTok{set\_date\_recorded(timestamp}\OperatorTok{.}\NormalTok{clone())}\OperatorTok{;}
\NormalTok{ id3tag\_inner}
\OperatorTok{.}\NormalTok{write\_to\_path(}\StringTok{"assets/a.mp3"}\OperatorTok{,} \PreprocessorTok{id3::Version::}\NormalTok{Id3v24)}
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to write!"}\NormalTok{)}\OperatorTok{;}
\KeywordTok{let}\NormalTok{ id3tag\_reload }\OperatorTok{=} \PreprocessorTok{id3::Tag::}\NormalTok{read\_from\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to read!"}\NormalTok{)}\OperatorTok{;}
\PreprocessorTok{assert\_eq!}\NormalTok{(id3tag\_reload}\OperatorTok{.}\NormalTok{date\_recorded()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(timestamp))}\OperatorTok{;}
\OperatorTok{\}}
\end{Highlighting}
\end{Shaded}
We have finished a nice book.
\bibliography{book.bib,packages.bib} \bibliography{book.bib,packages.bib}

261
docs/conversion.html Normal file
View file

@ -0,0 +1,261 @@
<!DOCTYPE html>
<html lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Chapter 2 Conversion | audiotags Manual</title>
<meta name="description" content="This is the manual of the Rust crate audiotags" />
<meta name="generator" content="bookdown 0.21 and GitBook 2.6.7" />
<meta property="og:title" content="Chapter 2 Conversion | audiotags Manual" />
<meta property="og:type" content="book" />
<meta property="og:description" content="This is the manual of the Rust crate audiotags" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Chapter 2 Conversion | audiotags Manual" />
<meta name="twitter:description" content="This is the manual of the Rust crate audiotags" />
<meta name="author" content="Tianyi Shi" />
<meta name="date" content="2020-10-27" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="prev" href="start-simple.html"/>
<link rel="next" href="anytag.html"/>
<script src="libs/header-attrs-2.4/header-attrs.js"></script>
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-clipboard.css" rel="stylesheet" />
<style type="text/css">
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">
<div class="book-summary">
<nav role="navigation">
<ul class="summary">
<li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li>
<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
</ul></li>
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
<li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
<li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i><a href="./">audiotags Manual</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<section class="normal" id="section-">
<div id="conversion" class="section level1" number="2">
<h1><span class="header-section-number">Chapter 2</span> Conversion</h1>
<p>The following example shows how you can read the tag in an <code>mp3</code> file, convert it into an <code>mp4</code> tag, and write it to an <code>m4a</code> file.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="conversion.html#cb2-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span>Config<span class="op">,</span> Tag<span class="op">,</span> TagType<span class="op">};</span></span>
<span id="cb2-2"><a href="conversion.html#cb2-2" aria-hidden="true"></a></span>
<span id="cb2-3"><a href="conversion.html#cb2-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb2-4"><a href="conversion.html#cb2-4" aria-hidden="true"></a> <span class="co">// we have an mp3 and an m4a file</span></span>
<span id="cb2-5"><a href="conversion.html#cb2-5" aria-hidden="true"></a> <span class="kw">const</span> MP3_FILE<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;static</span> <span class="dt">str</span> <span class="op">=</span> <span class="st">&quot;assets/a.mp3&quot;</span><span class="op">;</span></span>
<span id="cb2-6"><a href="conversion.html#cb2-6" aria-hidden="true"></a> <span class="kw">const</span> M4A_FILE<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;static</span> <span class="dt">str</span> <span class="op">=</span> <span class="st">&quot;assets/a.m4a&quot;</span><span class="op">;</span></span>
<span id="cb2-7"><a href="conversion.html#cb2-7" aria-hidden="true"></a> <span class="co">// read tag from the mp3 file. Using `default()` so that the type of tag is guessed from the file extension</span></span>
<span id="cb2-8"><a href="conversion.html#cb2-8" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp3tag <span class="op">=</span> <span class="pp">Tag::</span><span class="kw">default</span>()<span class="op">.</span>read_from_path(MP3_FILE)<span class="op">.</span>unwrap()<span class="op">;</span></span>
<span id="cb2-9"><a href="conversion.html#cb2-9" aria-hidden="true"></a> <span class="co">// set the title</span></span>
<span id="cb2-10"><a href="conversion.html#cb2-10" aria-hidden="true"></a> mp3tag<span class="op">.</span>set_title(<span class="st">&quot;title from mp3 file&quot;</span>)<span class="op">;</span></span>
<span id="cb2-11"><a href="conversion.html#cb2-11" aria-hidden="true"></a> <span class="co">// we can convert it to an mp4 tag and save it to an m4a file.</span></span>
<span id="cb2-12"><a href="conversion.html#cb2-12" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp4tag <span class="op">=</span> mp3tag<span class="op">.</span>into_tag(<span class="pp">TagType::</span>Mp4)<span class="op">;</span></span>
<span id="cb2-13"><a href="conversion.html#cb2-13" aria-hidden="true"></a> mp4tag<span class="op">.</span>write_to_path(M4A_FILE)<span class="op">.</span>unwrap()<span class="op">;</span></span>
<span id="cb2-14"><a href="conversion.html#cb2-14" aria-hidden="true"></a></span>
<span id="cb2-15"><a href="conversion.html#cb2-15" aria-hidden="true"></a> <span class="co">// reload the tag from the m4a file; this time specifying the tag type (you can also use `default()`)</span></span>
<span id="cb2-16"><a href="conversion.html#cb2-16" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp4tag <span class="op">=</span> <span class="pp">Tag::</span>with_tag_type(<span class="pp">TagType::</span>Mp4)</span>
<span id="cb2-17"><a href="conversion.html#cb2-17" aria-hidden="true"></a> <span class="op">.</span>read_from_path(M4A_FILE)</span>
<span id="cb2-18"><a href="conversion.html#cb2-18" aria-hidden="true"></a> <span class="op">.</span>unwrap()<span class="op">;</span></span>
<span id="cb2-19"><a href="conversion.html#cb2-19" aria-hidden="true"></a> <span class="co">// the tag originated from an mp3 file is successfully written to an m4a file!</span></span>
<span id="cb2-20"><a href="conversion.html#cb2-20" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(mp4tag<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">&quot;title from mp3 file&quot;</span>))<span class="op">;</span></span>
<span id="cb2-21"><a href="conversion.html#cb2-21" aria-hidden="true"></a> <span class="co">// multiple artists</span></span>
<span id="cb2-22"><a href="conversion.html#cb2-22" aria-hidden="true"></a> mp4tag<span class="op">.</span>add_artist(<span class="st">&quot;artist1 of mp4&quot;</span>)<span class="op">;</span></span>
<span id="cb2-23"><a href="conversion.html#cb2-23" aria-hidden="true"></a> mp4tag<span class="op">.</span>add_artist(<span class="st">&quot;artist2 of mp4&quot;</span>)<span class="op">;</span></span>
<span id="cb2-24"><a href="conversion.html#cb2-24" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(</span>
<span id="cb2-25"><a href="conversion.html#cb2-25" aria-hidden="true"></a> mp4tag<span class="op">.</span>artists()<span class="op">,</span></span>
<span id="cb2-26"><a href="conversion.html#cb2-26" aria-hidden="true"></a> <span class="cn">Some</span>(<span class="pp">vec!</span>[<span class="st">&quot;artist1 of mp4&quot;</span><span class="op">,</span> <span class="st">&quot;artist2 of mp4&quot;</span>])</span>
<span id="cb2-27"><a href="conversion.html#cb2-27" aria-hidden="true"></a> )<span class="op">;</span></span>
<span id="cb2-28"><a href="conversion.html#cb2-28" aria-hidden="true"></a> <span class="co">// convert to id3 tag, which does not support multiple artists</span></span>
<span id="cb2-29"><a href="conversion.html#cb2-29" aria-hidden="true"></a> mp4tag<span class="op">.</span>set_config(<span class="pp">Config::</span><span class="kw">default</span>()<span class="op">.</span>sep_artist(<span class="st">&quot;/&quot;</span>))<span class="op">;</span></span>
<span id="cb2-30"><a href="conversion.html#cb2-30" aria-hidden="true"></a> <span class="co">// separator is by default `;` but we can customise it</span></span>
<span id="cb2-31"><a href="conversion.html#cb2-31" aria-hidden="true"></a> <span class="kw">let</span> mp3tag <span class="op">=</span> mp4tag<span class="op">.</span>into_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
<span id="cb2-32"><a href="conversion.html#cb2-32" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(mp3tag<span class="op">.</span>artist()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">&quot;artist1 of mp4/artist2 of mp4&quot;</span>))<span class="op">;</span></span>
<span id="cb2-33"><a href="conversion.html#cb2-33" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
</div>
</section>
</div>
</div>
</div>
<a href="start-simple.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="anytag.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
</div>
</div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
<script src="libs/gitbook-2.6.7/js/clipboard.min.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-clipboard.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": false,
"facebook": true,
"twitter": true,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"all": ["facebook", "twitter", "linkedin", "weibo", "instapaper"]
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": null,
"text": null
},
"history": {
"link": null,
"text": null
},
"view": {
"link": null,
"text": null
},
"download": ["audiotags.pdf", "audiotags.epub"],
"toc": {
"collapse": "subsection"
}
});
});
</script>
</body>
</html>

263
docs/downcast.html Normal file
View file

@ -0,0 +1,263 @@
<!DOCTYPE html>
<html lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Chapter 4 Downcast | audiotags Manual</title>
<meta name="description" content="This is the manual of the Rust crate audiotags" />
<meta name="generator" content="bookdown 0.21 and GitBook 2.6.7" />
<meta property="og:title" content="Chapter 4 Downcast | audiotags Manual" />
<meta property="og:type" content="book" />
<meta property="og:description" content="This is the manual of the Rust crate audiotags" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Chapter 4 Downcast | audiotags Manual" />
<meta name="twitter:description" content="This is the manual of the Rust crate audiotags" />
<meta name="author" content="Tianyi Shi" />
<meta name="date" content="2020-10-27" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="prev" href="anytag.html"/>
<link rel="next" href="references.html"/>
<script src="libs/header-attrs-2.4/header-attrs.js"></script>
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-clipboard.css" rel="stylesheet" />
<style type="text/css">
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">
<div class="book-summary">
<nav role="navigation">
<ul class="summary">
<li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li>
<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
</ul></li>
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
<li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
<li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i><a href="./">audiotags Manual</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<section class="normal" id="section-">
<div id="downcast" class="section level1" number="4">
<h1><span class="header-section-number">Chapter 4</span> Downcast</h1>
<p>The following example shows how you can downcast a <code>Box&lt;dyn AudioTag&gt;</code> into its “backend” tag type. This allows you to set the uncommon metadata supported by the corresponding backend but not by <strong>audiotags</strong>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="downcast.html#cb4-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">*;</span></span>
<span id="cb4-2"><a href="downcast.html#cb4-2" aria-hidden="true"></a></span>
<span id="cb4-3"><a href="downcast.html#cb4-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb4-4"><a href="downcast.html#cb4-4" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> innertag <span class="op">=</span> <span class="pp">metaflac::Tag::</span><span class="kw">default</span>()<span class="op">;</span></span>
<span id="cb4-5"><a href="downcast.html#cb4-5" aria-hidden="true"></a> innertag</span>
<span id="cb4-6"><a href="downcast.html#cb4-6" aria-hidden="true"></a> <span class="op">.</span>vorbis_comments_mut()</span>
<span id="cb4-7"><a href="downcast.html#cb4-7" aria-hidden="true"></a> <span class="op">.</span>set_title(<span class="pp">vec!</span>[<span class="st">&quot;title from metaflac::Tag&quot;</span>])<span class="op">;</span></span>
<span id="cb4-8"><a href="downcast.html#cb4-8" aria-hidden="true"></a> <span class="kw">let</span> tag<span class="op">:</span> FlacTag <span class="op">=</span> innertag<span class="op">.</span>into()<span class="op">;</span></span>
<span id="cb4-9"><a href="downcast.html#cb4-9" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> id3tag <span class="op">=</span> tag<span class="op">.</span>into_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
<span id="cb4-10"><a href="downcast.html#cb4-10" aria-hidden="true"></a> id3tag</span>
<span id="cb4-11"><a href="downcast.html#cb4-11" aria-hidden="true"></a> <span class="op">.</span>write_to_path(<span class="st">&quot;assets/a.mp3&quot;</span>)</span>
<span id="cb4-12"><a href="downcast.html#cb4-12" aria-hidden="true"></a> <span class="op">.</span>expect(<span class="st">&quot;Fail to write!&quot;</span>)<span class="op">;</span></span>
<span id="cb4-13"><a href="downcast.html#cb4-13" aria-hidden="true"></a></span>
<span id="cb4-14"><a href="downcast.html#cb4-14" aria-hidden="true"></a> <span class="kw">let</span> id3tag_reload <span class="op">=</span> <span class="pp">Tag::</span><span class="kw">default</span>()</span>
<span id="cb4-15"><a href="downcast.html#cb4-15" aria-hidden="true"></a> <span class="op">.</span>read_from_path(<span class="st">&quot;assets/a.mp3&quot;</span>)</span>
<span id="cb4-16"><a href="downcast.html#cb4-16" aria-hidden="true"></a> <span class="op">.</span>expect(<span class="st">&quot;Fail to read!&quot;</span>)<span class="op">;</span></span>
<span id="cb4-17"><a href="downcast.html#cb4-17" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(id3tag_reload<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">&quot;title from metaflac::Tag&quot;</span>))<span class="op">;</span></span>
<span id="cb4-18"><a href="downcast.html#cb4-18" aria-hidden="true"></a></span>
<span id="cb4-19"><a href="downcast.html#cb4-19" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> id3tag_inner<span class="op">:</span> <span class="pp">id3::</span>Tag <span class="op">=</span> <span class="pp">downcast!</span>(id3tag_reload<span class="op">,</span> Id3v2Tag)<span class="op">;</span></span>
<span id="cb4-20"><a href="downcast.html#cb4-20" aria-hidden="true"></a> <span class="kw">let</span> timestamp <span class="op">=</span> <span class="pp">id3::</span>Timestamp <span class="op">{</span></span>
<span id="cb4-21"><a href="downcast.html#cb4-21" aria-hidden="true"></a> year<span class="op">:</span> <span class="dv">2013</span><span class="op">,</span></span>
<span id="cb4-22"><a href="downcast.html#cb4-22" aria-hidden="true"></a> month<span class="op">:</span> <span class="cn">Some</span>(<span class="dv">2u8</span>)<span class="op">,</span></span>
<span id="cb4-23"><a href="downcast.html#cb4-23" aria-hidden="true"></a> day<span class="op">:</span> <span class="cn">Some</span>(<span class="dv">5u8</span>)<span class="op">,</span></span>
<span id="cb4-24"><a href="downcast.html#cb4-24" aria-hidden="true"></a> hour<span class="op">:</span> <span class="cn">Some</span>(<span class="dv">6u8</span>)<span class="op">,</span></span>
<span id="cb4-25"><a href="downcast.html#cb4-25" aria-hidden="true"></a> minute<span class="op">:</span> <span class="cn">None</span><span class="op">,</span></span>
<span id="cb4-26"><a href="downcast.html#cb4-26" aria-hidden="true"></a> second<span class="op">:</span> <span class="cn">None</span><span class="op">,</span></span>
<span id="cb4-27"><a href="downcast.html#cb4-27" aria-hidden="true"></a> <span class="op">};</span></span>
<span id="cb4-28"><a href="downcast.html#cb4-28" aria-hidden="true"></a> id3tag_inner<span class="op">.</span>set_date_recorded(timestamp<span class="op">.</span>clone())<span class="op">;</span></span>
<span id="cb4-29"><a href="downcast.html#cb4-29" aria-hidden="true"></a> id3tag_inner</span>
<span id="cb4-30"><a href="downcast.html#cb4-30" aria-hidden="true"></a> <span class="op">.</span>write_to_path(<span class="st">&quot;assets/a.mp3&quot;</span><span class="op">,</span> <span class="pp">id3::Version::</span>Id3v24)</span>
<span id="cb4-31"><a href="downcast.html#cb4-31" aria-hidden="true"></a> <span class="op">.</span>expect(<span class="st">&quot;Fail to write!&quot;</span>)<span class="op">;</span></span>
<span id="cb4-32"><a href="downcast.html#cb4-32" aria-hidden="true"></a></span>
<span id="cb4-33"><a href="downcast.html#cb4-33" aria-hidden="true"></a> <span class="kw">let</span> id3tag_reload <span class="op">=</span> <span class="pp">id3::Tag::</span>read_from_path(<span class="st">&quot;assets/a.mp3&quot;</span>)<span class="op">.</span>expect(<span class="st">&quot;Fail to read!&quot;</span>)<span class="op">;</span></span>
<span id="cb4-34"><a href="downcast.html#cb4-34" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(id3tag_reload<span class="op">.</span>date_recorded()<span class="op">,</span> <span class="cn">Some</span>(timestamp))<span class="op">;</span></span>
<span id="cb4-35"><a href="downcast.html#cb4-35" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
</div>
</section>
</div>
</div>
</div>
<a href="anytag.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="references.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
</div>
</div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
<script src="libs/gitbook-2.6.7/js/clipboard.min.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-clipboard.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": false,
"facebook": true,
"twitter": true,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"all": ["facebook", "twitter", "linkedin", "weibo", "instapaper"]
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": null,
"text": null
},
"history": {
"link": null,
"text": null
},
"view": {
"link": null,
"text": null
},
"download": ["audiotags.pdf", "audiotags.epub"],
"toc": {
"collapse": "subsection"
}
});
});
</script>
</body>
</html>

View file

@ -133,9 +133,14 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
<li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li> <li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li>
<li class="divider"></li> <li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a></li> <li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
</ul></li>
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li> <li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
<li class="chapter" data-level="2" data-path="final-words.html"><a href="final-words.html"><i class="fa fa-check"></i><b>2</b> Final Words</a></li> <li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li> <li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
<li class="divider"></li> <li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li> <li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
@ -172,7 +177,16 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
<li>If you believe that serious stuff must be rendered by LaTeX as I do, there is a LaTex-rendered PDF for you to download (click the download button on the top)</li> <li>If you believe that serious stuff must be rendered by LaTeX as I do, there is a LaTex-rendered PDF for you to download (click the download button on the top)</li>
<li>If you love to read on a Kindle, there is also an epub output (click the download button on the top).</li> <li>If you love to read on a Kindle, there is also an epub output (click the download button on the top).</li>
</ul> </ul>
<div id="examples-in-this-manual" class="section level3 unnumbered">
<h3>Examples in this manual</h3>
<p>If you want to run the examples in this book:</p>
<ol style="list-style-type: decimal">
<li>clone the <a href="https://github.com/TianyiShi2001/audiotags">repo</a> and navigate into it</li>
<li>create <code>src/main.rs</code></li>
<li>all examples, unless otherwise specified, can be copied verbatim from this book to <code>src/main.rs</code> and run with <code>cargo run</code> (if youre reading it online, the copy button wil show if you hover over a code block)</li>
</ol>
</div>
</div> </div>
</section> </section>

View file

@ -1,2 +1,4 @@
start-simple start-simple
final-words conversion
anytag
downcast

View file

@ -31,7 +31,7 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="prev" href="final-words.html"/> <link rel="prev" href="downcast.html"/>
<script src="libs/header-attrs-2.4/header-attrs.js"></script> <script src="libs/header-attrs-2.4/header-attrs.js"></script>
<script src="libs/jquery-2.2.3/jquery.min.js"></script> <script src="libs/jquery-2.2.3/jquery.min.js"></script>
@ -133,9 +133,14 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
<li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li> <li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li>
<li class="divider"></li> <li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a></li> <li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
</ul></li>
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li> <li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
<li class="chapter" data-level="2" data-path="final-words.html"><a href="final-words.html"><i class="fa fa-check"></i><b>2</b> Final Words</a></li> <li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li> <li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
<li class="divider"></li> <li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li> <li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
@ -166,7 +171,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
</div> </div>
</div> </div>
</div> </div>
<a href="final-words.html" class="navigation navigation-prev navigation-unique" aria-label="Previous page"><i class="fa fa-angle-left"></i></a> <a href="downcast.html" class="navigation navigation-prev navigation-unique" aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
</div> </div>
</div> </div>

File diff suppressed because one or more lines are too long

View file

@ -32,7 +32,7 @@
<link rel="prev" href="index.html"/> <link rel="prev" href="index.html"/>
<link rel="next" href="final-words.html"/> <link rel="next" href="conversion.html"/>
<script src="libs/header-attrs-2.4/header-attrs.js"></script> <script src="libs/header-attrs-2.4/header-attrs.js"></script>
<script src="libs/jquery-2.2.3/jquery.min.js"></script> <script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" /> <link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
@ -133,9 +133,14 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
<li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li> <li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li>
<li class="divider"></li> <li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a></li> <li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
</ul></li>
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li> <li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
<li class="chapter" data-level="2" data-path="final-words.html"><a href="final-words.html"><i class="fa fa-check"></i><b>2</b> Final Words</a></li> <li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li> <li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
<li class="divider"></li> <li class="divider"></li>
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li> <li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
@ -202,7 +207,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
</div> </div>
</div> </div>
<a href="index.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a> <a href="index.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="final-words.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a> <a href="conversion.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
</div> </div>
</div> </div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script> <script src="libs/gitbook-2.6.7/js/app.min.js"></script>

View file

@ -1,3 +1,8 @@
# Conversion
The following example shows how you can read the tag in an `mp3` file, convert it into an `mp4` tag, and write it to an `m4a` file.
```rust
use audiotags::{Config, Tag, TagType}; use audiotags::{Config, Tag, TagType};
fn main() { fn main() {
@ -31,3 +36,4 @@ fn main() {
let mp3tag = mp4tag.into_tag(TagType::Id3v2); let mp3tag = mp4tag.into_tag(TagType::Id3v2);
assert_eq!(mp3tag.artist(), Some("artist1 of mp4/artist2 of mp4")); assert_eq!(mp3tag.artist(), Some("artist1 of mp4/artist2 of mp4"));
} }
```

View file

@ -1,10 +1,16 @@
# `AnyTag`
The following example shows how you can create a "generic" `AnyTag` and convert it into a specific tag type.
```rust
use audiotags::{AnyTag, AudioTagEdit, Id3v2Tag}; use audiotags::{AnyTag, AudioTagEdit, Id3v2Tag};
#[test] fn main() {
fn test_anytag() {
let mut tag = AnyTag::default(); let mut tag = AnyTag::default();
tag.set_title("foo"); tag.set_title("foo");
tag.set_year(2001); tag.set_year(2001);
let tag: Id3v2Tag = tag.into(); let tag: Id3v2Tag = tag.into();
assert_eq!(tag.year(), Some(2001)); assert_eq!(tag.year(), Some(2001));
tag.write_to_path("assets/a.mp3").unwrap();
} }
```

41
rtfm/04-downcast.Rmd Normal file
View file

@ -0,0 +1,41 @@
# Downcast
The following example shows how you can downcast a `Box<dyn AudioTag>` into its "backend" tag type. This allows you to set the uncommon metadata supported by the corresponding backend but not by **audiotags**.
```rust
use audiotags::*;
fn main() {
let mut innertag = metaflac::Tag::default();
innertag
.vorbis_comments_mut()
.set_title(vec!["title from metaflac::Tag"]);
let tag: FlacTag = innertag.into();
let mut id3tag = tag.into_tag(TagType::Id3v2);
id3tag
.write_to_path("assets/a.mp3")
.expect("Fail to write!");
let id3tag_reload = Tag::default()
.read_from_path("assets/a.mp3")
.expect("Fail to read!");
assert_eq!(id3tag_reload.title(), Some("title from metaflac::Tag"));
let mut id3tag_inner: id3::Tag = downcast!(id3tag_reload, Id3v2Tag);
let timestamp = id3::Timestamp {
year: 2013,
month: Some(2u8),
day: Some(5u8),
hour: Some(6u8),
minute: None,
second: None,
};
id3tag_inner.set_date_recorded(timestamp.clone());
id3tag_inner
.write_to_path("assets/a.mp3", id3::Version::Id3v24)
.expect("Fail to write!");
let id3tag_reload = id3::Tag::read_from_path("assets/a.mp3").expect("Fail to read!");
assert_eq!(id3tag_reload.date_recorded(), Some(timestamp));
}
```

View file

@ -1,3 +0,0 @@
# Final Words
We have finished a nice book.

View file

@ -22,3 +22,11 @@ Before you start, please let me introduce to you some great features of **bookdo
- If you believe that serious stuff must be rendered by LaTeX as I do, there is a LaTex-rendered PDF for you to download (click the download button on the top) - If you believe that serious stuff must be rendered by LaTeX as I do, there is a LaTex-rendered PDF for you to download (click the download button on the top)
- If you love to read on a Kindle, there is also an epub output (click the download button on the top). - If you love to read on a Kindle, there is also an epub output (click the download button on the top).
'` '`
### Examples in this manual {-}
If you want to run the examples in this book:
1. clone the [repo](https://github.com/TianyiShi2001/audiotags) and navigate into it
2. create `src/main.rs`
3. all examples, unless otherwise specified, can be copied verbatim from this book to `src/main.rs` and run with `cargo run` (if you're reading it online, the copy button wil show if you hover over a code block)

View file

@ -17,11 +17,6 @@ fn test_inner() {
.expect("Fail to read!"); .expect("Fail to read!");
assert_eq!(id3tag_reload.title(), Some("title from metaflac::Tag")); assert_eq!(id3tag_reload.title(), Some("title from metaflac::Tag"));
// let mut id3tag_inner: id3::Tag = id3tag_reload
// .into_any()
// .downcast_ref::<Id3v2Tag>()
// .unwrap()
// .into();
let mut id3tag_inner: id3::Tag = downcast!(id3tag_reload, Id3v2Tag); let mut id3tag_inner: id3::Tag = downcast!(id3tag_reload, Id3v2Tag);
let timestamp = id3::Timestamp { let timestamp = id3::Timestamp {
year: 2013, year: 2013,