All pastes #413894 Raw Edit

Someone

public text v1 · immutable
#413894 ·published 2007-03-28 19:23 UTC
rendered paste body
Index: 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;
+}