685 lines
13 KiB
C++
685 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2008-2012 Paul Davis <paul@linuxaudiosystems.com>
|
|
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
|
|
* Copyright (C) 2009 David Robillard <d@drobilla.net>
|
|
* Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
|
|
* Copyright (C) 2015 Colin Fletcher <colin.m.fletcher@googlemail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "ardour/session_metadata.h"
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
using namespace std;
|
|
using namespace Glib;
|
|
using namespace ARDOUR;
|
|
|
|
SessionMetadata *SessionMetadata::_metadata = NULL; //singleton instance
|
|
|
|
SessionMetadata::SessionMetadata ()
|
|
{
|
|
/*** General ***/
|
|
map.insert (Property ("description", ""));
|
|
|
|
/*** Track/Song Data ***/
|
|
map.insert (Property ("comment", ""));
|
|
map.insert (Property ("copyright", ""));
|
|
map.insert (Property ("isrc", ""));
|
|
map.insert (Property ("year", ""));
|
|
|
|
/*** Title and friends ***/
|
|
map.insert (Property ("grouping", ""));
|
|
map.insert (Property ("title", ""));
|
|
map.insert (Property ("subtitle", ""));
|
|
|
|
/*** People... ***/
|
|
map.insert (Property ("artist", ""));
|
|
map.insert (Property ("album_artist", ""));
|
|
map.insert (Property ("lyricist", ""));
|
|
map.insert (Property ("composer", ""));
|
|
map.insert (Property ("conductor", ""));
|
|
map.insert (Property ("remixer", ""));
|
|
map.insert (Property ("arranger", ""));
|
|
map.insert (Property ("engineer", ""));
|
|
map.insert (Property ("producer", ""));
|
|
map.insert (Property ("dj_mixer", ""));
|
|
map.insert (Property ("mixer", ""));
|
|
//map.insert (Property ("performers", "")); // Multiple values [instrument]
|
|
|
|
/*** Education... ***/
|
|
map.insert (Property ("instructor", ""));
|
|
map.insert (Property ("course", ""));
|
|
|
|
/*** Album info ***/
|
|
map.insert (Property ("album", ""));
|
|
map.insert (Property ("compilation", ""));
|
|
map.insert (Property ("disc_subtitle", ""));
|
|
map.insert (Property ("disc_number", ""));
|
|
map.insert (Property ("total_discs", ""));
|
|
map.insert (Property ("track_number", ""));
|
|
map.insert (Property ("total_tracks", ""));
|
|
|
|
/*** Style ***/
|
|
map.insert (Property ("genre", ""));
|
|
//map.insert (Property ("mood", ""));
|
|
//map.insert (Property ("bpm", ""));
|
|
|
|
/*** Other ***/
|
|
//map.insert (Property ("lyrics", ""));
|
|
//map.insert (Property ("media", ""));
|
|
//map.insert (Property ("label", ""));
|
|
map.insert (Property ("barcode", ""));
|
|
//map.insert (Property ("encoded_by", ""));
|
|
//map.insert (Property ("catalog_number", ""));
|
|
|
|
/*** Sorting orders ***/
|
|
//map.insert (Property ("album_sort", ""));
|
|
//map.insert (Property ("album_artist_sort", ""));
|
|
//map.insert (Property ("artist_sort", ""));
|
|
//map.insert (Property ("title_sort", ""));
|
|
|
|
/*** Globals ***/
|
|
user_map.insert (Property ("user_name", ""));
|
|
user_map.insert (Property ("user_email", ""));
|
|
user_map.insert (Property ("user_web", ""));
|
|
user_map.insert (Property ("user_organization", ""));
|
|
user_map.insert (Property ("user_country", ""));
|
|
}
|
|
|
|
SessionMetadata::~SessionMetadata ()
|
|
{
|
|
|
|
}
|
|
|
|
XMLNode *
|
|
SessionMetadata::get_xml (const string & name) const
|
|
{
|
|
string value = get_value (name);
|
|
if (value.empty()) {
|
|
return 0;
|
|
}
|
|
|
|
XMLNode val ("value", value);
|
|
XMLNode * node = new XMLNode (name);
|
|
node->add_child_copy (val);
|
|
|
|
return node;
|
|
}
|
|
|
|
string
|
|
SessionMetadata::get_value (const string & name) const
|
|
{
|
|
PropertyMap::const_iterator it = map.find (name);
|
|
if (it == map.end()) {
|
|
it = user_map.find (name);
|
|
if (it == user_map.end()) {
|
|
// Should not be reached, except if loading metadata from a newer version with a new type
|
|
std::cerr << "Programming error in SessionMetadata::get_value (" << name << ")" << std::endl;
|
|
return "";
|
|
}
|
|
}
|
|
|
|
return it->second;
|
|
}
|
|
|
|
uint32_t
|
|
SessionMetadata::get_uint_value (const string & name) const
|
|
{
|
|
return atoi (get_value (name).c_str());
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_value (const string & name, const string & value)
|
|
{
|
|
PropertyMap::iterator it = map.find (name);
|
|
if (it == map.end()) {
|
|
it = user_map.find (name);
|
|
if (it == user_map.end()) {
|
|
// Should not be reached, except if loading metadata from a newer version with a new type
|
|
std::cerr << "Programming error in SessionMetadata::set_value (" << name << ")" << std::endl;
|
|
return;
|
|
}
|
|
}
|
|
|
|
it->second = value;
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_value (const string & name, uint32_t value)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << value;
|
|
if (oss.str().compare("0")) {
|
|
set_value (name, oss.str());
|
|
} else {
|
|
set_value (name, "");
|
|
}
|
|
}
|
|
|
|
/*** Serialization ***/
|
|
XMLNode &
|
|
SessionMetadata::get_state () const
|
|
{
|
|
XMLNode * node = new XMLNode ("Metadata");
|
|
XMLNode * prop;
|
|
|
|
for (PropertyMap::const_iterator it = map.begin(); it != map.end(); ++it) {
|
|
if ((prop = get_xml (it->first))) {
|
|
node->add_child_nocopy (*prop);
|
|
}
|
|
}
|
|
|
|
return *node;
|
|
}
|
|
|
|
int
|
|
SessionMetadata::set_state (const XMLNode & state, int /*version_num*/)
|
|
{
|
|
const XMLNodeList & children = state.children();
|
|
string name;
|
|
string value;
|
|
XMLNode * node;
|
|
|
|
for (XMLNodeConstIterator it = children.begin(); it != children.end(); it++) {
|
|
node = *it;
|
|
if (node->children().empty()) {
|
|
continue;
|
|
}
|
|
|
|
name = node->name();
|
|
node = *node->children().begin();
|
|
value = node->content();
|
|
|
|
set_value (name, value);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
XMLNode &
|
|
SessionMetadata::get_user_state ()
|
|
{
|
|
XMLNode * node = new XMLNode ("Metadata");
|
|
XMLNode * prop;
|
|
|
|
for (PropertyMap::const_iterator it = user_map.begin(); it != user_map.end(); ++it) {
|
|
if ((prop = get_xml (it->first))) {
|
|
node->add_child_nocopy (*prop);
|
|
}
|
|
}
|
|
|
|
return *node;
|
|
}
|
|
|
|
/*** Accessing ***/
|
|
string
|
|
SessionMetadata::description () const
|
|
{
|
|
return get_value("description");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::comment () const
|
|
{
|
|
return get_value("comment");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::copyright () const
|
|
{
|
|
return get_value("copyright");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::isrc () const
|
|
{
|
|
return get_value("isrc");
|
|
}
|
|
|
|
uint32_t
|
|
SessionMetadata::year () const
|
|
{
|
|
return get_uint_value("year");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::grouping () const
|
|
{
|
|
return get_value("grouping");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::barcode () const
|
|
{
|
|
return get_value("barcode");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::title () const
|
|
{
|
|
return get_value("title");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::subtitle () const
|
|
{
|
|
return get_value("subtitle");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::artist () const
|
|
{
|
|
return get_value("artist");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::album_artist () const
|
|
{
|
|
return get_value("album_artist");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::lyricist () const
|
|
{
|
|
return get_value("lyricist");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::composer () const
|
|
{
|
|
return get_value("composer");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::conductor () const
|
|
{
|
|
return get_value("conductor");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::remixer () const
|
|
{
|
|
return get_value("remixer");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::arranger () const
|
|
{
|
|
return get_value("arranger");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::engineer () const
|
|
{
|
|
return get_value("engineer");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::producer () const
|
|
{
|
|
return get_value("producer");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::dj_mixer () const
|
|
{
|
|
return get_value("dj_mixer");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::mixer () const
|
|
{
|
|
return get_value("mixer");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::album () const
|
|
{
|
|
return get_value("album");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::compilation () const
|
|
{
|
|
return get_value("compilation");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::disc_subtitle () const
|
|
{
|
|
return get_value("disc_subtitle");
|
|
}
|
|
|
|
uint32_t
|
|
SessionMetadata::disc_number () const
|
|
{
|
|
return get_uint_value("disc_number");
|
|
}
|
|
|
|
uint32_t
|
|
SessionMetadata::total_discs () const
|
|
{
|
|
return get_uint_value("total_discs");
|
|
}
|
|
|
|
uint32_t
|
|
SessionMetadata::track_number () const
|
|
{
|
|
return get_uint_value("track_number");
|
|
}
|
|
|
|
uint32_t
|
|
SessionMetadata::total_tracks () const
|
|
{
|
|
return get_uint_value("total_tracks");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::genre () const
|
|
{
|
|
return get_value("genre");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::instructor () const
|
|
{
|
|
return get_value("instructor");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::course () const
|
|
{
|
|
return get_value("course");
|
|
}
|
|
|
|
|
|
string
|
|
SessionMetadata::user_name () const
|
|
{
|
|
return get_value("user_name");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::user_email () const
|
|
{
|
|
return get_value("user_email");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::user_web () const
|
|
{
|
|
return get_value("user_web");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::organization () const
|
|
{
|
|
return get_value("user_organization");
|
|
}
|
|
|
|
string
|
|
SessionMetadata::country () const
|
|
{
|
|
return get_value("user_country");
|
|
}
|
|
|
|
|
|
|
|
/*** Editing ***/
|
|
void
|
|
SessionMetadata::set_description (const string & v)
|
|
{
|
|
set_value ("description", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_comment (const string & v)
|
|
{
|
|
set_value ("comment", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_copyright (const string & v)
|
|
{
|
|
set_value ("copyright", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_isrc (const string & v)
|
|
{
|
|
set_value ("isrc", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_year (uint32_t v)
|
|
{
|
|
set_value ("year", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_grouping (const string & v)
|
|
{
|
|
set_value ("grouping", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_barcode (const string & v)
|
|
{
|
|
set_value ("barcode", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_title (const string & v)
|
|
{
|
|
set_value ("title", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_subtitle (const string & v)
|
|
{
|
|
set_value ("subtitle", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_artist (const string & v)
|
|
{
|
|
set_value ("artist", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_album_artist (const string & v)
|
|
{
|
|
set_value ("album_artist", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_lyricist (const string & v)
|
|
{
|
|
set_value ("lyricist", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_composer (const string & v)
|
|
{
|
|
set_value ("composer", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_conductor (const string & v)
|
|
{
|
|
set_value ("conductor", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_remixer (const string & v)
|
|
{
|
|
set_value ("remixer", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_arranger (const string & v)
|
|
{
|
|
set_value ("arranger", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_engineer (const string & v)
|
|
{
|
|
set_value ("engineer", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_producer (const string & v)
|
|
{
|
|
set_value ("producer", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_dj_mixer (const string & v)
|
|
{
|
|
set_value ("dj_mixer", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_mixer (const string & v)
|
|
{
|
|
set_value ("mixer", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_album (const string & v)
|
|
{
|
|
set_value ("album", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_compilation (const string & v)
|
|
{
|
|
set_value ("compilation", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_disc_subtitle (const string & v)
|
|
{
|
|
set_value ("disc_subtitle", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_disc_number (uint32_t v)
|
|
{
|
|
set_value ("disc_number", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_total_discs (uint32_t v)
|
|
{
|
|
set_value ("total_discs", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_track_number (uint32_t v)
|
|
{
|
|
set_value ("track_number", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_total_tracks (uint32_t v)
|
|
{
|
|
set_value ("total_tracks", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_genre (const string & v)
|
|
{
|
|
set_value ("genre", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_instructor (const string & v)
|
|
{
|
|
set_value ("instructor", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_course (const string & v)
|
|
{
|
|
set_value ("course", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_user_name (const string & v)
|
|
{
|
|
set_value ("user_name", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_user_email (const string & v)
|
|
{
|
|
set_value ("user_email", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_user_web (const string & v)
|
|
{
|
|
set_value ("user_web", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::set_organization (const string & v)
|
|
{
|
|
set_value ("user_organization", v);
|
|
}
|
|
void
|
|
SessionMetadata::set_country (const string & v)
|
|
{
|
|
set_value ("user_country", v);
|
|
}
|
|
|
|
void
|
|
SessionMetadata::av_export_tag (MetaDataMap& meta) const
|
|
{
|
|
/* this is used for ffmpeg/liblame -metadata key=value
|
|
* (video and mp3 export).
|
|
* for flac/ogg's vorbis-comment see:
|
|
* AudiofileTagger::tag_generic()
|
|
* AudiofileTagger::tag_vorbis_comment()
|
|
*/
|
|
if (year() > 0) {
|
|
std::ostringstream osstream; osstream << year();
|
|
meta["year"] = osstream.str();
|
|
}
|
|
if (track_number() > 0) {
|
|
std::ostringstream osstream; osstream << track_number();
|
|
meta["track"] = osstream.str();
|
|
}
|
|
if (disc_number() > 0) {
|
|
std::ostringstream osstream; osstream << disc_number();
|
|
meta["disc"] = osstream.str();
|
|
}
|
|
if (!title().empty()) { meta["title"] = title(); }
|
|
if (!artist().empty()) { meta["author"] = artist(); }
|
|
if (!album_artist().empty()) { meta["album_artist"] = album_artist(); }
|
|
if (!album().empty()) { meta["album"] = album(); }
|
|
if (!genre().empty()) { meta["genre"] = genre(); }
|
|
if (!composer().empty()) { meta["composer"] = composer(); }
|
|
if (!comment().empty()) { meta["comment"] = comment(); }
|
|
if (!copyright().empty()) { meta["copyright"] = copyright(); }
|
|
if (!subtitle().empty()) { meta["description"] = subtitle(); }
|
|
}
|