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/.RData
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/l/audiotags.svg)](https://crates.io/crates/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.

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}!
\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}{%
\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{Shaded}
\hypertarget{final-words}{%
\chapter{Final Words}\label{final-words}}
\hypertarget{conversion}{%
\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}

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 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="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="divider"></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 love to read on a Kindle, there is also an epub output (click the download button on the top).</li>
</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>
</section>

View file

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

View file

@ -31,7 +31,7 @@
<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/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 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="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="divider"></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>
<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>

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="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/jquery-2.2.3/jquery.min.js"></script>
<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 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="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="divider"></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>
<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>
<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};
fn main() {
@ -31,3 +36,4 @@ fn main() {
let mp3tag = mp4tag.into_tag(TagType::Id3v2);
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};
#[test]
fn test_anytag() {
fn main() {
let mut tag = AnyTag::default();
tag.set_title("foo");
tag.set_year(2001);
let tag: Id3v2Tag = tag.into();
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 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!");
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 timestamp = id3::Timestamp {
year: 2013,