summaryrefslogtreecommitdiff
path: root/src/libaudcore/tuple.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libaudcore/tuple.cc')
-rw-r--r--src/libaudcore/tuple.cc156
1 files changed, 93 insertions, 63 deletions
diff --git a/src/libaudcore/tuple.cc b/src/libaudcore/tuple.cc
index 52fd29b..4cd29b6 100644
--- a/src/libaudcore/tuple.cc
+++ b/src/libaudcore/tuple.cc
@@ -62,13 +62,14 @@ struct TupleData
uint64_t setmask; // which fields are present
Index<TupleVal> vals; // ordered list of field values
- int *subtunes; /**< Array of int containing subtune index numbers.
+ short * subtunes; /**< Array of int containing subtune index numbers.
Can be nullptr if indexing is linear or if
there are no subtunes. */
- int nsubtunes; /**< Number of subtunes, if any. Values greater than 0
+ short nsubtunes; /**< Number of subtunes, if any. Values greater than 0
mean that there are subtunes and #subtunes array
may be set. */
+ short state;
int refcount;
TupleData ();
@@ -85,7 +86,7 @@ struct TupleData
TupleVal * lookup (int field, bool add, bool remove);
void set_int (int field, int x);
void set_str (int field, const char * str);
- void set_subtunes (int nsubs, const int * subs);
+ void set_subtunes (short nsubs, const short * subs);
static TupleData * ref (TupleData * tuple);
static void unref (TupleData * tuple);
@@ -107,27 +108,28 @@ static const struct {
{"title", Tuple::String, FallbackTitle},
{"artist", Tuple::String, FallbackArtist},
{"album", Tuple::String, FallbackAlbum},
+ {"album-artist", Tuple::String, -1},
{"comment", Tuple::String, -1},
{"genre", Tuple::String, -1},
+ {"year", Tuple::Int, -1},
+
+ {"composer", Tuple::String, -1},
+ {"performer", Tuple::String, -1},
+ {"copyright", Tuple::String, -1},
+ {"date", Tuple::String, -1},
{"track-number", Tuple::Int, -1},
{"length", Tuple::Int, -1},
- {"year", Tuple::Int, -1},
- {"quality", Tuple::String, -1},
+
+ {"bitrate", Tuple::Int, -1},
{"codec", Tuple::String, -1},
+ {"quality", Tuple::String, -1},
{"file-name", Tuple::String, -1},
{"file-path", Tuple::String, -1},
{"file-ext", Tuple::String, -1},
- {"album-artist", Tuple::String, -1},
- {"composer", Tuple::String, -1},
- {"performer", Tuple::String, -1},
- {"copyright", Tuple::String, -1},
- {"date", Tuple::String, -1},
- {"mbid", Tuple::String, -1},
- {"mime-type", Tuple::String, -1},
- {"bitrate", Tuple::Int, -1},
+ {"audio-file", Tuple::String, -1},
{"subsong-id", Tuple::Int, -1},
{"subsong-num", Tuple::Int, -1},
@@ -162,6 +164,7 @@ static const FieldDictEntry field_dict[] = {
{"album", Tuple::Album},
{"album-artist", Tuple::AlbumArtist},
{"artist", Tuple::Artist},
+ {"audio-file", Tuple::AudioFile},
{"bitrate", Tuple::Bitrate},
{"codec", Tuple::Codec},
{"comment", Tuple::Comment},
@@ -180,8 +183,6 @@ static const FieldDictEntry field_dict[] = {
{"gain-track-peak", Tuple::TrackPeak},
{"genre", Tuple::Genre},
{"length", Tuple::Length},
- {"mbid", Tuple::MusicBrainz},
- {"mime-type", Tuple::MIMEType},
{"performer", Tuple::Performer},
{"quality", Tuple::Quality},
{"segment-end", Tuple::EndTime},
@@ -277,17 +278,17 @@ void TupleData::set_str (int field, const char * str)
new (& val->str) String (str);
}
-void TupleData::set_subtunes (int nsubs, const int * subs)
+void TupleData::set_subtunes (short nsubs, const short * subs)
{
nsubtunes = nsubs;
- delete subtunes;
+ delete[] subtunes;
subtunes = nullptr;
- if (subs)
+ if (nsubs && subs)
{
- subtunes = new int[nsubs];
- memcpy (subtunes, subs, sizeof (int) * nsubs);
+ subtunes = new short[nsubs];
+ memcpy (subtunes, subs, sizeof subtunes[0] * nsubs);
}
}
@@ -295,12 +296,14 @@ TupleData::TupleData () :
setmask (0),
subtunes (nullptr),
nsubtunes (0),
+ state (Tuple::Initial),
refcount (1) {}
TupleData::TupleData (const TupleData & other) :
setmask (other.setmask),
subtunes (nullptr),
nsubtunes (0),
+ state (other.state),
refcount (1)
{
vals.insert (0, other.vals.len ());
@@ -345,8 +348,8 @@ TupleData::~TupleData ()
bool TupleData::is_same (const TupleData & other)
{
- if (setmask != other.setmask || nsubtunes != other.nsubtunes ||
- (! subtunes) != (! other.subtunes))
+ if (state != other.state || setmask != other.setmask ||
+ nsubtunes != other.nsubtunes || (! subtunes) != (! other.subtunes))
return false;
auto a = vals.begin ();
@@ -371,7 +374,7 @@ bool TupleData::is_same (const TupleData & other)
}
}
- if (subtunes && memcmp (subtunes, other.subtunes, sizeof (int) * nsubtunes))
+ if (subtunes && memcmp (subtunes, other.subtunes, sizeof subtunes[0] * nsubtunes))
return false;
return true;
@@ -427,6 +430,17 @@ EXPORT Tuple Tuple::ref () const
return tuple;
}
+EXPORT Tuple::State Tuple::state () const
+{
+ return data ? (Tuple::State) data->state : Initial;
+}
+
+EXPORT void Tuple::set_state (State st)
+{
+ data = TupleData::copy_on_write (data);
+ data->state = st;
+}
+
EXPORT Tuple::ValueType Tuple::get_value_type (Field field) const
{
assert (is_valid_field (field));
@@ -553,18 +567,18 @@ EXPORT void Tuple::set_format (const char * format, int chans, int rate, int bra
set_int (Bitrate, brate);
}
-EXPORT void Tuple::set_subtunes (int n_subtunes, const int * subtunes)
+EXPORT void Tuple::set_subtunes (short n_subtunes, const short * subtunes)
{
data = TupleData::copy_on_write (data);
data->set_subtunes (n_subtunes, subtunes);
}
-EXPORT int Tuple::get_n_subtunes () const
+EXPORT short Tuple::get_n_subtunes() const
{
return data ? data->nsubtunes : 0;
}
-EXPORT int Tuple::get_nth_subtune (int n) const
+EXPORT short Tuple::get_nth_subtune (short n) const
{
if (! data || n < 0 || n >= data->nsubtunes)
return -1;
@@ -644,10 +658,10 @@ EXPORT bool Tuple::fetch_stream_info (VFSFile & stream)
* be modified, and the string returned will use the same memory. May return
* nullptr. */
-static char * split_folder (char * path)
+static char * split_folder (char * path, char sep)
{
char * c;
- while ((c = strrchr (path, G_DIR_SEPARATOR)))
+ while ((c = strrchr (path, sep)))
{
* c = 0;
if (c[1])
@@ -657,31 +671,33 @@ static char * split_folder (char * path)
return path[0] ? path : nullptr;
}
-/* Separates the domain name from an internet URI. The string passed will be
- * modified, and the string returned will share the same memory. May return
- * nullptr. Examples:
+/* These two functions separate the domain name from an internet URL. Examples:
* "http://some.domain.org/folder/file.mp3" -> "some.domain.org"
* "http://some.stream.fm:8000" -> "some.stream.fm" */
-static char * domain_name (char * name)
+static const char * find_domain (const char * name)
{
if (! strncmp (name, "http://", 7))
- name += 7;
- else if (! strncmp (name, "https://", 8))
- name += 8;
- else if (! strncmp (name, "mms://", 6))
- name += 6;
- else
- return nullptr;
+ return name + 7;
+ if (! strncmp (name, "https://", 8))
+ return name + 8;
+ if (! strncmp (name, "mms://", 6))
+ return name + 6;
+
+ return nullptr;
+}
+static StringBuf extract_domain (const char * start)
+{
+ StringBuf name = str_copy (start);
char * c;
if ((c = strchr (name, '/')))
- * c = 0;
+ name.resize (c - name);
if ((c = strchr (name, ':')))
- * c = 0;
+ name.resize (c - name);
if ((c = strchr (name, '?')))
- * c = 0;
+ name.resize (c - name);
return name;
}
@@ -701,10 +717,22 @@ EXPORT void Tuple::generate_fallbacks ()
data = TupleData::copy_on_write (data);
+ // use album artist, if present
+ if (! artist && (artist = get_str (AlbumArtist)))
+ {
+ data->set_str (FallbackArtist, artist);
+
+ if (album)
+ return; // nothing left to do
+ }
+
auto filepath = get_str (Path);
if (! filepath)
return;
+ const char * s;
+ char sep;
+
if (! strcmp (filepath, "cdda://"))
{
// audio CD:
@@ -713,38 +741,40 @@ EXPORT void Tuple::generate_fallbacks ()
if (! album)
data->set_str (FallbackAlbum, _("Audio CD"));
}
- else if (strstr (filepath, "://"))
+ else if ((s = find_domain (filepath)))
{
- // URL:
+ // internet URL:
// use the domain name as the album
- if (album)
- return;
-
- StringBuf buf = str_copy (filepath);
- const char * domain = domain_name (buf);
-
- if (domain)
- data->set_str (FallbackAlbum, domain);
+ if (! album)
+ data->set_str (FallbackAlbum, extract_domain (s));
}
else
{
- // local file:
+ // any other URI:
// use the top two path elements as the artist and album
- if (artist && album)
- return;
-
- StringBuf buf;
-#ifdef _WIN32
- if (filepath[0] && filepath[1] == ':' && filepath[2] == '\\')
- buf.steal (str_copy (filepath + 3));
+ if ((s = strstr (filepath, "://")))
+ {
+ s += 3;
+ sep = '/';
+ }
else
+ {
+#ifdef _WIN32
+ if (g_ascii_isalpha (filepath[0]) && filepath[1] == ':')
+ s = filepath + 2;
+ else
#endif
- buf.steal (str_copy (filepath));
+ s = filepath;
+
+ sep = G_DIR_SEPARATOR;
+ }
+
+ StringBuf buf = str_copy (s);
- char * first = split_folder (buf);
- char * second = (first && first > buf) ? split_folder (buf) : nullptr;
+ char * first = split_folder (buf, sep);
+ char * second = (first && first > buf) ? split_folder (buf, sep) : nullptr;
// skip common strings and avoid duplicates
for (auto skip : (const char *[]) {"~", "music", artist, album, get_str (Genre)})