[mythtv] [PATCH] MythMusic On Demand Loading
John Hurliman
jhurliman at myrealbox.com
Mon Apr 21 00:08:58 EDT 2003
(Hey I got the subject right this time). This is the beginning of my
attempts to speed up the load time for mythmusic when using large audio
archives and/or CD-based media. I'm submitting it because I'm stuck
right now and need a little help. I wrote a new function
AllMusic::checkFilesInTree() which calls MusicNode::checkYourself()
which calls the existing CheckFile function. CheckFile was modified to
run in two modes, just update the database with an id, filename, minimal
info, and the second runs a full CheckFile (actually opens the file and
gets things like length or id3 tag). The problem is I'm calling
all_music->checkFilesInTree() from startPlayback() and it's checking the
entire tree each time you go to the PlaybackBox screen. I need to make
it only check the files which will show up in the PlaybackBox or take a
completely different approach. I think I'm way off base here but it's a
start.
John Hurliman
-------------- next part --------------
Index: cddecoder.cpp
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/cddecoder.cpp,v
retrieving revision 1.12
diff -u -r1.12 cddecoder.cpp
--- cddecoder.cpp 25 Mar 2003 20:12:06 -0000 1.12
+++ cddecoder.cpp 21 Apr 2003 05:50:14 -0000
@@ -315,8 +315,9 @@
return getMetadata();
}
-Metadata* CdDecoder::getMetadata(QSqlDatabase *x)
+Metadata* CdDecoder::getMetadata(QSqlDatabase *x, bool readFile)
{
+ readFile = false;
x = x ;
return getMetadata();
}
Index: cddecoder.h
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/cddecoder.h,v
retrieving revision 1.7
diff -u -r1.7 cddecoder.h
--- cddecoder.h 25 Mar 2003 20:12:06 -0000 1.7
+++ cddecoder.h 21 Apr 2003 05:50:14 -0000
@@ -25,7 +25,7 @@
int getNumTracks(void);
Metadata *getMetadata(QSqlDatabase *db, int track);
- Metadata *getMetadata(QSqlDatabase *db);
+ Metadata *getMetadata(QSqlDatabase *db, bool readFile);
Metadata *getMetadata(int track);
Metadata *getMetadata();
void commitMetadata(Metadata *mdata);
Index: decoder.h
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/decoder.h,v
retrieving revision 1.4
diff -u -r1.4 decoder.h
--- decoder.h 5 Feb 2003 19:47:54 -0000 1.4
+++ decoder.h 21 Apr 2003 05:50:15 -0000
@@ -78,7 +78,7 @@
static Decoder *create(const QString &, QIODevice *, Output *,
bool = FALSE);
- virtual Metadata *getMetadata(QSqlDatabase *db) = 0;
+ virtual Metadata *getMetadata(QSqlDatabase *db, bool readFile) = 0;
virtual void commitMetadata(Metadata *mdata) = 0;
protected:
Index: flacdecoder.cpp
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/flacdecoder.cpp,v
retrieving revision 1.5
diff -u -r1.5 flacdecoder.cpp
--- flacdecoder.cpp 5 Feb 2003 19:47:54 -0000 1.5
+++ flacdecoder.cpp 21 Apr 2003 05:50:17 -0000
@@ -408,75 +408,81 @@
char *field_value;
} Argument_VcField;
-Metadata *FlacDecoder::getMetadata(QSqlDatabase *db)
+Metadata *FlacDecoder::getMetadata(QSqlDatabase *db, bool readFile)
{
Metadata *testdb = new Metadata(filename);
- if (testdb->isInDatabase(db))
- return testdb;
-
+ if(!readFile)
+ {
+ if (testdb->isInDatabase(db))
+ return testdb;
+ }
+
delete testdb;
QString artist = "", album = "", title = "", genre = "";
int year = 0, tracknum = 0, length = 0;
- FILE *input = fopen(filename.ascii(), "r");
-
- if (!input)
- return NULL;
-
- FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
- if (!FLAC__metadata_chain_read(chain, filename.ascii()))
+ if(readFile)
{
- FLAC__metadata_chain_delete(chain);
- return NULL;
- }
-
- bool found_vc_block = false;
- FLAC__StreamMetadata *block = 0;
- FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
+ FILE *input = fopen(filename.ascii(), "r");
- FLAC__metadata_iterator_init(iterator, chain);
+ if (!input)
+ return NULL;
- block = FLAC__metadata_iterator_get_block(iterator);
+ FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
+ if (!FLAC__metadata_chain_read(chain, filename.ascii()))
+ {
+ FLAC__metadata_chain_delete(chain);
+ return NULL;
+ }
+
+ bool found_vc_block = false;
+ FLAC__StreamMetadata *block = 0;
+ FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
- FLAC__ASSERT(0 != block);
- FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
+ FLAC__metadata_iterator_init(iterator, chain);
- int samplerate = block->data.stream_info.sample_rate;
- int totalsamples = block->data.stream_info.total_samples;
- int bytesperms = (samplerate) / 1000;
+ block = FLAC__metadata_iterator_get_block(iterator);
- length = totalsamples / bytesperms;
+ FLAC__ASSERT(0 != block);
+ FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
- do {
- block = FLAC__metadata_iterator_get_block(iterator);
- if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
- found_vc_block = true;
- } while (!found_vc_block && FLAC__metadata_iterator_next(iterator));
+ int samplerate = block->data.stream_info.sample_rate;
+ int totalsamples = block->data.stream_info.total_samples;
+ int bytesperms = (samplerate) / 1000;
+
+ length = totalsamples / bytesperms;
+
+ do {
+ block = FLAC__metadata_iterator_get_block(iterator);
+ if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
+ found_vc_block = true;
+ } while (!found_vc_block && FLAC__metadata_iterator_next(iterator));
+
+ if (!found_vc_block)
+ {
+ FLAC__metadata_chain_delete(chain);
+ FLAC__metadata_iterator_delete(iterator);
+ return NULL;
+ }
+
+ FLAC__ASSERT(0 != block);
+ FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+ artist = getComment(block, "artist");
+ album = getComment(block, "album");
+ title = getComment(block, "title");
+ genre = getComment(block, "genre");
+ tracknum = getComment(block, "tracknumber").toInt();
+ year = getComment(block, "date").toInt();
- if (!found_vc_block)
- {
FLAC__metadata_chain_delete(chain);
FLAC__metadata_iterator_delete(iterator);
- return NULL;
}
- FLAC__ASSERT(0 != block);
- FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
-
- artist = getComment(block, "artist");
- album = getComment(block, "album");
- title = getComment(block, "title");
- genre = getComment(block, "genre");
- tracknum = getComment(block, "tracknumber").toInt();
- year = getComment(block, "date").toInt();
-
Metadata *retdata = new Metadata(filename, artist, album, title, genre,
year, tracknum, length);
-
- FLAC__metadata_chain_delete(chain);
- FLAC__metadata_iterator_delete(iterator);
-
+
retdata->dumpToDatabase(db);
return retdata;
Index: flacdecoder.h
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/flacdecoder.h,v
retrieving revision 1.4
diff -u -r1.4 flacdecoder.h
--- flacdecoder.h 5 Feb 2003 19:47:54 -0000 1.4
+++ flacdecoder.h 21 Apr 2003 05:50:17 -0000
@@ -21,7 +21,7 @@
void doWrite(const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
void setFlacMetadata(const FLAC__StreamMetadata *metadata);
- Metadata *getMetadata(QSqlDatabase *db);
+ Metadata *getMetadata(QSqlDatabase *db, bool readFile);
void commitMetadata(Metadata *mdata);
private:
Index: maddecoder.cpp
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/maddecoder.cpp,v
retrieving revision 1.8
diff -u -r1.8 maddecoder.cpp
--- maddecoder.cpp 15 Apr 2003 21:38:58 -0000 1.8
+++ maddecoder.cpp 21 Apr 2003 05:50:20 -0000
@@ -529,11 +529,14 @@
return MAD_FLOW_STOP;
}
-Metadata *MadDecoder::getMetadata(QSqlDatabase *db)
+Metadata *MadDecoder::getMetadata(QSqlDatabase *db, bool readFile)
{
Metadata *testdb = new Metadata(filename);
- if (testdb->isInDatabase(db))
- return testdb;
+ if(!readFile)
+ {
+ if (testdb->isInDatabase(db))
+ return testdb;
+ }
delete testdb;
@@ -650,66 +653,69 @@
}
}
}
-
+
struct mad_stream stream;
struct mad_header header;
mad_timer_t timer;
- unsigned char buffer[8192];
- unsigned int buflen = 0;
+ if (readFile)
+ {
+ unsigned char buffer[8192];
+ unsigned int buflen = 0;
- mad_stream_init(&stream);
- mad_header_init(&header);
+ mad_stream_init(&stream);
+ mad_header_init(&header);
- timer = mad_timer_zero;
+ timer = mad_timer_zero;
- FILE *input = fopen(filename.ascii(), "r");
+ FILE *input = fopen(filename.ascii(), "r");
- while (1)
- {
- if (buflen < sizeof(buffer))
+ while (1)
{
- int bytes;
- bytes = fread(buffer + buflen, 1, sizeof(buffer) - buflen, input);
- if (bytes <= 0)
- break;
- buflen += bytes;
- }
+ if (buflen < sizeof(buffer))
+ {
+ int bytes;
+ bytes = fread(buffer + buflen, 1, sizeof(buffer) - buflen, input);
+ if (bytes <= 0)
+ break;
+ buflen += bytes;
+ }
- mad_stream_buffer(&stream, buffer, buflen);
+ mad_stream_buffer(&stream, buffer, buflen);
- while (1)
- {
- if (mad_header_decode(&header, &stream) == -1)
+ while (1)
{
- if (!MAD_RECOVERABLE(stream.error))
- break;
- if (stream.error == MAD_ERROR_LOSTSYNC)
+ if (mad_header_decode(&header, &stream) == -1)
{
- int tagsize = id3_tag_query(stream.this_frame,
- stream.bufend -
- stream.this_frame);
- if (tagsize > 0)
- mad_stream_skip(&stream, tagsize);
+ if (!MAD_RECOVERABLE(stream.error))
+ break;
+ if (stream.error == MAD_ERROR_LOSTSYNC)
+ {
+ int tagsize = id3_tag_query(stream.this_frame,
+ stream.bufend -
+ stream.this_frame);
+ if (tagsize > 0)
+ mad_stream_skip(&stream, tagsize);
+ }
}
+ mad_timer_add(&timer, header.duration);
}
- mad_timer_add(&timer, header.duration);
- }
- if (stream.error != MAD_ERROR_BUFLEN)
- break;
-
- memmove(buffer, stream.next_frame, &buffer[buflen] - stream.next_frame);
- buflen -= stream.next_frame - &buffer[0];
- }
+ if (stream.error != MAD_ERROR_BUFLEN)
+ break;
- mad_header_finish(&header);
- mad_stream_finish(&stream);
+ memmove(buffer, stream.next_frame, &buffer[buflen] - stream.next_frame);
+ buflen -= stream.next_frame - &buffer[0];
+ }
- fclose(input);
+ mad_header_finish(&header);
+ mad_stream_finish(&stream);
- length = mad_timer_count(timer, MAD_UNITS_MILLISECONDS);
+ fclose(input);
+ length = mad_timer_count(timer, MAD_UNITS_MILLISECONDS);
+ }
+
Metadata *retdata = new Metadata(filename, artist, album, title, genre,
year, tracknum, length);
Index: maddecoder.h
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/maddecoder.h,v
retrieving revision 1.5
diff -u -r1.5 maddecoder.h
--- maddecoder.h 5 Feb 2003 19:47:54 -0000 1.5
+++ maddecoder.h 21 Apr 2003 05:50:20 -0000
@@ -24,7 +24,7 @@
static const int maxFrameCheck;
static const int initialFrameSize;
- Metadata *getMetadata(QSqlDatabase *db);
+ Metadata *getMetadata(QSqlDatabase *db, bool readFile);
void commitMetadata(Metadata *mdata);
private:
Index: main.cpp
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/main.cpp,v
retrieving revision 1.39
diff -u -r1.39 main.cpp
--- main.cpp 18 Apr 2003 18:19:31 -0000 1.39
+++ main.cpp 21 Apr 2003 05:50:21 -0000
@@ -23,6 +23,8 @@
#include <mythtv/themedmenu.h>
#include <mythtv/mythcontext.h>
+#include "main.h"
+
MythContext *gContext;
void CheckFreeDBServerFile(void)
@@ -59,7 +61,7 @@
return decoder;
}
-void CheckFile(const QString &filename)
+void CheckFile(const QString &filename, bool readFile)
{
Decoder *decoder = getDecoder(filename);
@@ -67,7 +69,7 @@
{
QSqlDatabase *db = QSqlDatabase::database();
- Metadata *data = decoder->getMetadata(db);
+ Metadata *data = decoder->getMetadata(db, readFile);
if (data)
delete data;
@@ -211,7 +213,7 @@
{
if (*iter == kFileSystem)
{
- CheckFile(iter.key());
+ CheckFile(iter.key(), false);
}
else if (*iter == kDatabase)
{
@@ -231,6 +233,14 @@
void startPlayback(PlaylistsContainer *all_playlists, AllMusic *all_music)
{
+ if(!all_music)
+ {
+ cerr << "main.o: We are not going to get very far with a null pointer to metadata" << endl;
+ return;
+ }
+
+ all_music->checkFilesInTree();
+
PlaybackBox *pbb = new PlaybackBox(all_playlists, all_music);
pbb->Show();
Index: metadata.cpp
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/metadata.cpp,v
retrieving revision 1.22
diff -u -r1.22 metadata.cpp
--- metadata.cpp 12 Apr 2003 16:01:06 -0000 1.22
+++ metadata.cpp 21 Apr 2003 05:50:25 -0000
@@ -10,6 +10,7 @@
#include <mythtv/mythwidgets.h>
#include "metadata.h"
+#include "main.h"
bool operator==(const Metadata& a, const Metadata& b)
{
@@ -124,16 +125,28 @@
QString sqlfilename = filename;
sqlfilename.replace(QRegExp("\""), QString("\\\""));
- QString thequery = QString("INSERT INTO musicmetadata (artist,album,title,"
- "genre,year,tracknum,length,filename) VALUES "
- "(\"%1\",\"%2\",\"%3\",\"%4\",%5,%6,%7,\"%8\");")
- .arg(artist.latin1()).arg(album.latin1())
- .arg(title.latin1()).arg(genre).arg(year)
- .arg(tracknum).arg(length).arg(sqlfilename);
- db->exec(thequery);
+ QString updatequery = QString("UPDATE musicmetadata SET artist = \"%1\", "
+ "album = \"%2\", title = \"%3\", genre = \"%4\", "
+ "year = \"%5\", tracknum = \"%6\", "
+ "length = \"%7\" WHERE filename = \"%8\" LIMIT 1;")
+ .arg(artist.latin1()).arg(album.latin1())
+ .arg(title.latin1()).arg(genre).arg(year)
+ .arg(tracknum).arg(length).arg(sqlfilename);
+ QSqlQuery query = db->exec(updatequery);
+
+ if (query.numRowsAffected() == 0)
+ {
+ QString thequery = QString("INSERT INTO musicmetadata (artist,album,title,"
+ "genre,year,tracknum,length,filename) VALUES "
+ "(\"%1\",\"%2\",\"%3\",\"%4\",%5,%6,%7,\"%8\");")
+ .arg(artist.latin1()).arg(album.latin1())
+ .arg(title.latin1()).arg(genre).arg(year)
+ .arg(tracknum).arg(length).arg(sqlfilename);
+ db->exec(thequery);
- // easiest way to ensure we've got 'id' filled.
- fillData(db);
+ // easiest way to ensure we've got 'id' filled.
+ fillData(db);
+ }
}
void Metadata::setField(const QString &field, const QString &data)
@@ -542,6 +555,22 @@
}
}
+void AllMusic::checkFilesInTree()
+{
+ //FIXME: Display a progress dialog
+
+ root_node->checkYourself();
+ QPtrListIterator<MusicNode> iter( top_nodes );
+ MusicNode *checker;
+ while ( (checker = iter.current()) != 0 )
+ {
+ checker->checkYourself();
+ ++iter;
+ }
+
+ resync();
+}
+
void AllMusic::buildTree()
{
//
@@ -953,3 +982,22 @@
}
}
+void MusicNode::checkYourself()
+{
+ QPtrListIterator<Metadata> anit(my_tracks);
+ Metadata *a_track;
+ while( (a_track = anit.current() ) != 0)
+ {
+ QString filename = a_track->Filename();
+ CheckFile(filename, true);
+ ++anit;
+ }
+
+ QPtrListIterator<MusicNode> iter(my_subnodes);
+ MusicNode *check;
+ while( (check = iter.current() ) != 0)
+ {
+ check->checkYourself();
+ ++iter;
+ }
+}
Index: metadata.h
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/metadata.h,v
retrieving revision 1.12
diff -u -r1.12 metadata.h
--- metadata.h 12 Apr 2003 04:31:18 -0000 1.12
+++ metadata.h 21 Apr 2003 05:50:26 -0000
@@ -141,6 +141,7 @@
QString getTitle(){return my_title;}
MusicNode* findRightNode(QStringList tree_levels, Metadata *inserter, uint depth);
void printYourself(int indent_amount); // debugging
+ void checkYourself();
void clearTracks(){my_tracks.clear();}
void putYourselfOnTheListView(TreeCheckItem *parent, bool show_node);
void sort();
@@ -190,6 +191,7 @@
void setCDTitle(const QString &a_title){cd_title = a_title;}
void buildTree();
void printTree(); // debugging
+ void checkFilesInTree();
void sortTree();
void intoTree(Metadata* inserter);
MusicNode* findRightNode(Metadata* inserter, uint depth);
Index: vorbisdecoder.cpp
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/vorbisdecoder.cpp,v
retrieving revision 1.5
diff -u -r1.5 vorbisdecoder.cpp
--- vorbisdecoder.cpp 15 Apr 2003 21:38:58 -0000 1.5
+++ vorbisdecoder.cpp 21 Apr 2003 05:50:27 -0000
@@ -316,46 +316,52 @@
deinit();
}
-Metadata *VorbisDecoder::getMetadata(QSqlDatabase *db)
+Metadata *VorbisDecoder::getMetadata(QSqlDatabase *db, bool readFile)
{
Metadata *testdb = new Metadata(filename);
- if (testdb->isInDatabase(db))
- return testdb;
+ if(!readFile)
+ {
+ if (testdb->isInDatabase(db))
+ return testdb;
+ }
delete testdb;
QString artist = "", album = "", title = "", genre = "";
int year = 0, tracknum = 0, length = 0;
-
- FILE *input = fopen(filename.ascii(), "r");
-
- if (!input)
- return NULL;
-
- OggVorbis_File vf;
- vorbis_comment *comment = NULL;
-
- if (ov_open(input, &vf, NULL, 0))
+
+ if(readFile)
{
- fclose(input);
- return NULL;
- }
+ FILE *input = fopen(filename.ascii(), "r");
- comment = ov_comment(&vf, -1);
- length = (int)ov_time_total(&vf, -1) * 1000;
+ if (!input)
+ return NULL;
- artist = getComment(comment, "artist");
- album = getComment(comment, "album");
- title = getComment(comment, "title");
- genre = getComment(comment, "genre");
- tracknum = atoi(getComment(comment, "tracknumber").ascii());
- year = atoi(getComment(comment, "date").ascii());
+ OggVorbis_File vf;
+ vorbis_comment *comment = NULL;
- ov_clear(&vf);
+ if (ov_open(input, &vf, NULL, 0))
+ {
+ fclose(input);
+ return NULL;
+ }
+
+ comment = ov_comment(&vf, -1);
+ length = (int)ov_time_total(&vf, -1) * 1000;
+
+ artist = getComment(comment, "artist");
+ album = getComment(comment, "album");
+ title = getComment(comment, "title");
+ genre = getComment(comment, "genre");
+ tracknum = atoi(getComment(comment, "tracknumber").ascii());
+ year = atoi(getComment(comment, "date").ascii());
+ ov_clear(&vf);
+ }
+
Metadata *retdata = new Metadata(filename, artist, album, title, genre,
year, tracknum, length);
-
+
retdata->dumpToDatabase(db);
return retdata;
Index: vorbisdecoder.h
===================================================================
RCS file: /var/lib/cvs/mythmusic/mythmusic/vorbisdecoder.h,v
retrieving revision 1.4
diff -u -r1.4 vorbisdecoder.h
--- vorbisdecoder.h 5 Feb 2003 19:47:54 -0000 1.4
+++ vorbisdecoder.h 21 Apr 2003 05:50:27 -0000
@@ -18,7 +18,7 @@
void seek(double);
void stop();
- Metadata *getMetadata(QSqlDatabase *db);
+ Metadata *getMetadata(QSqlDatabase *db, bool readFile);
void commitMetadata(Metadata *mdata);
private:
-------------- next part --------------
void CheckFile(const QString &filename, bool readFile);
More information about the mythtv-dev
mailing list