rendered paste bodyIndex: mythmusic/playbackbox.cpp
===================================================================
--- mythmusic/playbackbox.cpp (revision 13144)
+++ mythmusic/playbackbox.cpp (working copy)
@@ -1355,6 +1355,9 @@
void PlaybackBoxMusic::stop(void)
{
+
+ saveMetadata();
+
stopDecoder();
if (output)
@@ -1406,6 +1409,18 @@
}
}
+void PlaybackBoxMusic::saveMetadata()
+{
+
+ if (curMeta && curMeta->hasChanged())
+ {
+ curMeta->persist();
+ if (decoder)
+ decoder->commitMetadata(curMeta);
+ }
+
+}
+
void PlaybackBoxMusic::previous()
{
if (repeatmode == REPEAT_ALL)
@@ -1965,6 +1980,9 @@
{
// It's a track
+ // Save changes to metadata
+ saveMetadata();
+
curMeta = all_music->getMetadata(node_int);
if (title_text)
title_text->SetText(curMeta->FormatTitle());
Index: mythmusic/metaio_libid3hack.h
===================================================================
--- mythmusic/metaio_libid3hack.h (revision 13144)
+++ mythmusic/metaio_libid3hack.h (working copy)
@@ -6,5 +6,6 @@
#define ID3_FILE_UPDATE myth_id3_file_update
int myth_id3_file_update(struct id3_file *file);
+int myth_id3_field_setintplus(union id3_field *field, id3_byte_t const *data, id3_length_t length);
}
#endif
Index: mythmusic/metadata.cpp
===================================================================
--- mythmusic/metadata.cpp (revision 13144)
+++ mythmusic/metadata.cpp (working copy)
@@ -72,6 +72,8 @@
if (!query.exec() || query.numRowsAffected() < 1)
MythContext::DBError("music persist", query);
+
+ m_changed = false;
}
int Metadata::compare(Metadata *other)
@@ -329,12 +331,14 @@
strQuery = "INSERT INTO music_songs ( directory_id, lastplay,"
" artist_id, album_id, name, genre_id,"
" year, track, length, filename,"
- " rating, format, date_entered, date_modified ) "
+ " rating, numplays, format, date_entered,"
+ " date_modified ) "
"VALUES ( "
" :DIRECTORY, :LASTPLAY,"
" :ARTIST, :ALBUM, :TITLE, :GENRE,"
" :YEAR, :TRACKNUM, :LENGTH, :FILENAME,"
- " :RATING, :FORMAT, :DATE_ADD, :DATE_MOD );";
+ " :RATING, :PLAYCOUNT,:FORMAT, :DATE_ADD,"
+ " :DATE_MOD );";
}
else
{
@@ -349,6 +353,7 @@
", length = :LENGTH"
", filename = :FILENAME"
", rating = :RATING"
+ ", numplays = :PLAYCOUNT"
", format = :FORMAT"
", date_modified = :DATE_MOD "
"WHERE song_id= :ID ;";
@@ -366,6 +371,7 @@
query.bindValue(":LENGTH", m_length);
query.bindValue(":FILENAME", sqlfilename.utf8());
query.bindValue(":RATING", m_rating);
+ query.bindValue(":PLAYCOUNT", m_playcount);
query.bindValue(":FORMAT", m_format);
query.bindValue(":DATE_MOD", QDateTime::currentDateTime());
Index: mythmusic/metaioid3v2.h
===================================================================
--- mythmusic/metaioid3v2.h (revision 13144)
+++ mythmusic/metaioid3v2.h (working copy)
@@ -11,6 +11,7 @@
#define MYTH_ID3_FRAME_COMPILATIONARTIST "TPE4"
#define MYTH_ID3_FRAME_COMMENT "TXXX"
#define MYTH_ID3_FRAME_MUSICBRAINZ_ALBUMARTISTDESC "MusicBrainz Album Artist Id"
+#define MYTH_ID3_FRAME_POPULARIMETER "POPM"
#define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
@@ -48,6 +49,8 @@
bool setComment(id3_tag *pTag, const char* pLabel, const QString value,
const QString desc = "");
+ bool setPopularimeter(id3_tag *pTag, const QString email, const int rating,
+ const QString playcount);
bool findXingHeader(xing *xing, struct mad_bitptr ptr, unsigned int bitlen);
};
Index: mythmusic/main.cpp
===================================================================
--- mythmusic/main.cpp (revision 13144)
+++ mythmusic/main.cpp (working copy)
@@ -427,12 +427,7 @@
static void postMusic(MusicData *mdata)
{
- // Automagically save all playlists and metadata (ratings) that have changed
- if (mdata->all_music->cleanOutThreads())
- {
- mdata->all_music->save();
- }
-
+ // Automagically save all playlists that have changed
if (mdata->all_playlists->cleanOutThreads())
{
mdata->all_playlists->save();
Index: mythmusic/playbackbox.h
===================================================================
--- mythmusic/playbackbox.h (revision 13144)
+++ mythmusic/playbackbox.h (working copy)
@@ -49,6 +49,7 @@
void pause();
void stop();
void stopDecoder();
+ void saveMetadata();
void previous();
void next();
void seekforward();
Index: mythmusic/metaioid3v2.cpp
===================================================================
--- mythmusic/metaioid3v2.cpp (revision 13144)
+++ mythmusic/metaioid3v2.cpp (working copy)
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
+#include <math.h>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
@@ -120,6 +121,13 @@
setComment(tag, ID3_FRAME_YEAR, QString("%1").arg(mdata->Year()));
}
+ if (mdata->Rating() > 0 || mdata->PlayCount() > 0)
+ {
+ removeComment(tag, MYTH_ID3_FRAME_POPULARIMETER, "devnull@mythtv.org");
+ int rating = (int) (mdata->Rating() / 10 * 255);
+ setPopularimeter(tag, "devnull@mythtv.org", rating, QString("%1").arg(mdata->PlayCount()));
+ }
+
// Write Genre maintaining the ID3v1 genre number if applicable
QString data = mdata->Genre();
if (!data.isEmpty())
@@ -139,21 +147,19 @@
QString("%1").arg(genrenum));
else
setComment(tag, ID3_FRAME_GENRE, data);
- }
-
+ }
+
if (0 != mdata->Track())
{
if (!exclusive) removeComment(tag, ID3_FRAME_TRACK);
setComment(tag, ID3_FRAME_TRACK, QString("%1").arg(mdata->Track()));
}
-
-
id3_tag_options(tag, ID3_TAG_OPTION_COMPRESSION, 0);
id3_tag_options(tag, ID3_TAG_OPTION_CRC, 0);
id3_tag_options(tag, ID3_TAG_OPTION_UNSYNCHRONISATION, 0);
id3_tag_options(tag, ID3_TAG_OPTION_ID3V1, 0);
-
+
// The id3_file_update function has a feature deficit.
// See the files: metaio_libid3hack.c/h
bool rv = (0 == ID3_FILE_UPDATE(p_input));
@@ -173,7 +179,7 @@
{
QString artist = "", compilation_artist = "", album = "", title = "",
genre = "";
- int year = 0, tracknum = 0, length = 0;
+ int year = 0, tracknum = 0, length = 0, playcount = 0, rating = 0, id = 0;
bool compilation = false;
id3_file *p_input = NULL;
@@ -243,6 +249,17 @@
// If the ID3v2 tag contains the length, then use it
length = getComment(tag, "TLEN").toInt();
+ // Read rating and play count
+ struct id3_frame *p_frame = 0;
+ for (int i=0; NULL != (p_frame = id3_tag_findframe(tag, MYTH_ID3_FRAME_POPULARIMETER, i)); ++i) {
+ QString popm_id = (const char*)p_frame->fields[0].latin1.ptr;
+ if (popm_id == "devnull@mythtv.org") {
+ rating = p_frame->fields[1].number.value;
+ playcount = QString::fromLatin1((const char *)p_frame->fields[2].binary.data).replace(QRegExp("^([0-9]*).*"), QString("\\1")).toInt();
+ playcount = (int) floor((playcount / 255 * 10) + 0.5);
+ }
+ }
+
id3_file_close(p_input);
}
@@ -264,7 +281,8 @@
}
Metadata *retdata = new Metadata(filename, artist, compilation_artist, album,
- title, genre, year, tracknum, length);
+ title, genre, year, tracknum, length,
+ id, rating, playcount);
retdata->setCompilation(compilation);
@@ -476,24 +494,37 @@
inline QString MetaIOID3v2::getRawID3String(union id3_field *pField)
{
QString tmp = "";
-
- id3_ucs4_t const *p_ucs4 = (id3_ucs4_t *) id3_field_getstring(pField);
-
- if (p_ucs4)
+
+ if (pField->type == ID3_FIELD_TYPE_LATIN1)
{
- id3_utf8_t *p_utf8 = id3_ucs4_utf8duplicate(p_ucs4);
-
- if (!p_utf8)
- return "";
- tmp = QString::fromUtf8((const char*)p_utf8);
+ id3_latin1_t const *p_latin1 = id3_field_getlatin1(pField);
+ tmp = QString("%1").arg((const char*)p_latin1);
- free(p_utf8);
}
- else
+ else if (pField->type == ID3_FIELD_TYPE_STRING)
{
+
+ id3_ucs4_t const *p_ucs4 = (id3_ucs4_t *) id3_field_getstring(pField);
+
+ if (p_ucs4)
+ {
+ id3_utf8_t *p_utf8 = id3_ucs4_utf8duplicate(p_ucs4);
+
+ if (!p_utf8)
+ return "";
+
+ tmp = QString::fromUtf8((const char*)p_utf8);
+
+ free(p_utf8);
+ }
+ }
+ else if (pField->type == ID3_FIELD_TYPE_STRINGLIST)
+ {
+ id3_ucs4_t const *p_ucs4;
+
unsigned int nstrings = id3_field_getnstrings(pField);
-
+
for (unsigned int j=0; j<nstrings; ++j)
{
p_ucs4 = id3_field_getstrings(pField, j);
@@ -501,17 +532,17 @@
if (!p_ucs4)
break;
- id3_utf8_t *p_utf8 = id3_ucs4_utf8duplicate(p_ucs4);
+ id3_utf8_t *p_utf8 = id3_ucs4_utf8duplicate(p_ucs4);
- if (!p_utf8)
- break;
+ if (!p_utf8)
+ break;
- tmp += QString::fromUtf8((const char*)p_utf8);
+ tmp += QString::fromUtf8((const char*)p_utf8);
- free(p_utf8);
- }
+ free(p_utf8);
+ }
}
-
+
return tmp;
}
@@ -546,8 +577,13 @@
}
else
{
+ QString tmp = "";
+
// Get the description to compare
- QString tmp = getRawID3String(&p_frame->fields[1]);
+ if (pLabel == MYTH_ID3_FRAME_POPULARIMETER)
+ tmp = getRawID3String(&p_frame->fields[0]);
+ else
+ tmp = getRawID3String(&p_frame->fields[1]);
// Let's compare the descriptions.
if (tmp == desc)
@@ -702,3 +738,48 @@
return true;
}
+
+/*!
+ * \brief Function to set the Rating
+ *
+ * \param pTag Pointer to a id3_file object
+ * \param email The user or player indentifier, in the form of an email address
+ * \param rating The track rating between 0 and 255
+ * \param playcount The track play count
+ * \returns True or False depending on success
+ */
+bool MetaIOID3v2::setPopularimeter(id3_tag *pTag,
+ const QString email,
+ const int rating,
+ const QString playcount)
+{
+ struct id3_frame* p_frame = NULL;
+
+ p_frame = id3_frame_new(MYTH_ID3_FRAME_POPULARIMETER);
+
+ if (NULL == p_frame)
+ return false;
+
+ if (email.isEmpty() ||
+ rating < 0 || rating > 255)
+ {
+ id3_frame_delete(p_frame);
+ return false;
+ }
+
+ id3_field_setlatin1(&p_frame->fields[0], (const id3_latin1_t*)(const char *)email);
+ id3_field_setint(&p_frame->fields[1], rating);
+
+ const id3_byte_t* playcount_to_char = (const id3_byte_t*)(const char *)playcount;
+
+ myth_id3_field_setintplus(&p_frame->fields[2], playcount_to_char, sizeof(*playcount_to_char));
+
+ if (0 != id3_tag_attachframe(pTag, p_frame))
+ {
+ VERBOSE(VB_GENERAL, "Failed to set POPM Tag");
+ id3_frame_delete(p_frame);
+ return false;
+ }
+
+ return true;
+}
Index: mythmusic/metaio_libid3hack.c
===================================================================
--- mythmusic/metaio_libid3hack.c (revision 13144)
+++ mythmusic/metaio_libid3hack.c (working copy)
@@ -229,7 +229,7 @@
/* render ID3v2 */
- id3_tag_options(file->primary, ID3_TAG_OPTION_ID3V1, 0);
+ //id3_tag_options(file->primary, ID3_TAG_OPTION_ID3V1, 0);
v2size = id3_tag_render(file->primary, 0);
if (v2size) {
@@ -281,3 +281,31 @@
return result;
}
+int myth_id3_field_setintplus(union id3_field *field, id3_byte_t const *data, id3_length_t length)
+{
+ if (!field)
+ return -1;
+
+ if (field->type != ID3_FIELD_TYPE_INT32PLUS)
+ return -1;
+
+ id3_byte_t *mem;
+
+ if (length == 0)
+ mem = 0;
+ else {
+ mem = malloc(length);
+ if (mem == 0)
+ return -1;
+
+ if (!data)
+ return -1;
+
+ memcpy(mem, data, length);
+ }
+
+ field->binary.data = mem;
+ field->binary.length = length;
+
+ return 0;
+}