mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-31 11:35:24 +01:00
better .cue spec conformity (allow many files in one sheet, use the SONGWRITER field as song's composer, ignore data files)
This commit is contained in:
parent
bb79a68be0
commit
d4d7f19fab
@ -29,6 +29,7 @@ const char* CueParser::kIndexRegExp = "(\\d{2}):(\\d{2}):(\\d{2})";
|
||||
|
||||
const char* CueParser::kPerformer = "performer";
|
||||
const char* CueParser::kTitle = "title";
|
||||
const char* CueParser::kSongWriter = "songwriter";
|
||||
const char* CueParser::kFile = "file";
|
||||
const char* CueParser::kTrack = "track";
|
||||
const char* CueParser::kIndex = "index";
|
||||
@ -46,15 +47,23 @@ SongList CueParser::Load(QIODevice* device, const QDir& dir) const {
|
||||
text_stream.setCodec(QTextCodec::codecForUtfText(device->peek(1024), QTextCodec::codecForName("UTF-8")));
|
||||
|
||||
QString dir_path = dir.absolutePath();
|
||||
// read the first line already
|
||||
QString line = text_stream.readLine();
|
||||
|
||||
QString line;
|
||||
QList<CueEntry> entries;
|
||||
int files = 0;
|
||||
|
||||
// -- whole file
|
||||
while (!text_stream.atEnd()) {
|
||||
|
||||
QString album_artist;
|
||||
QString album;
|
||||
QString album_composer;
|
||||
QString file;
|
||||
QString file_type;
|
||||
|
||||
// header
|
||||
while (!(line = text_stream.readLine()).isNull()) {
|
||||
// -- FILE section
|
||||
do {
|
||||
QStringList splitted = SplitCueLine(line);
|
||||
|
||||
// uninteresting or incorrect line
|
||||
@ -75,6 +84,11 @@ SongList CueParser::Load(QIODevice* device, const QDir& dir) const {
|
||||
|
||||
album = line_value;
|
||||
|
||||
// SONGWRITER
|
||||
} else if(line_name == kSongWriter) {
|
||||
|
||||
album_composer = line_value;
|
||||
|
||||
// FILE
|
||||
} else if(line_name == kFile) {
|
||||
|
||||
@ -82,29 +96,37 @@ SongList CueParser::Load(QIODevice* device, const QDir& dir) const {
|
||||
? line_value
|
||||
: dir.absoluteFilePath(line_value);
|
||||
|
||||
if(splitted.size() > 2) {
|
||||
file_type = splitted[2];
|
||||
}
|
||||
|
||||
// end of the header -> go into the track mode
|
||||
} else if(line_name == kTrack) {
|
||||
|
||||
files++;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// just ignore the rest of possible field types for now...
|
||||
}
|
||||
} while(!(line = text_stream.readLine()).isNull());
|
||||
|
||||
if(line.isNull()) {
|
||||
qWarning() << "the .cue file from " << dir_path << " defines no tracks!";
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if this is a data file, all of it's tracks will be ignored
|
||||
bool valid_file = file_type.compare("BINARY", Qt::CaseInsensitive) &&
|
||||
file_type.compare("MOTOROLA", Qt::CaseInsensitive);
|
||||
|
||||
QString track_type;
|
||||
QString index;
|
||||
QString artist;
|
||||
QString composer;
|
||||
QString title;
|
||||
|
||||
QList<CueEntry> entries;
|
||||
|
||||
// tracks
|
||||
// TRACK section
|
||||
do {
|
||||
QStringList splitted = SplitCueLine(line);
|
||||
|
||||
@ -121,8 +143,9 @@ SongList CueParser::Load(QIODevice* device, const QDir& dir) const {
|
||||
|
||||
// the beginning of another track's definition - we're saving the current one
|
||||
// for later (if it's valid of course)
|
||||
if(!index.isEmpty() && (track_type.isEmpty() || track_type == kAudioTrackType)) {
|
||||
entries.append(CueEntry(file, index, title, artist, album_artist, album));
|
||||
// please note that the same code is repeated just after this 'do-while' loop
|
||||
if(valid_file && !index.isEmpty() && (track_type.isEmpty() || track_type == kAudioTrackType)) {
|
||||
entries.append(CueEntry(file, index, title, artist, album_artist, album, composer, album_composer));
|
||||
}
|
||||
|
||||
// clear the state
|
||||
@ -155,14 +178,24 @@ SongList CueParser::Load(QIODevice* device, const QDir& dir) const {
|
||||
|
||||
title = line_value;
|
||||
|
||||
} else if(line_name == kSongWriter) {
|
||||
|
||||
composer = line_value;
|
||||
|
||||
// end of track's for the current file -> parse next one
|
||||
} else if(line_name == kFile) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// just ignore the rest of possible field types for now...
|
||||
} while(!(line = text_stream.readLine()).isNull());
|
||||
|
||||
// we didn't add the last song yet...
|
||||
if(!index.isEmpty() && (track_type.isEmpty() || track_type == kAudioTrackType)) {
|
||||
entries.append(CueEntry(file, index, title, artist, album_artist, album));
|
||||
if(valid_file && !index.isEmpty() && (track_type.isEmpty() || track_type == kAudioTrackType)) {
|
||||
entries.append(CueEntry(file, index, title, artist, album_artist, album, composer, album_composer));
|
||||
}
|
||||
}
|
||||
|
||||
// finalize parsing songs
|
||||
@ -181,7 +214,12 @@ SongList CueParser::Load(QIODevice* device, const QDir& dir) const {
|
||||
|
||||
// overwrite the stuff, we may have read from the file or library, using
|
||||
// the current .cue metadata
|
||||
|
||||
// set track number only in single-file mode
|
||||
if(files == 1) {
|
||||
song.set_track(i + 1);
|
||||
}
|
||||
|
||||
if(i + 1 < entries.size()) {
|
||||
// incorrect indices?
|
||||
if(!UpdateSong(entry, entries.at(i + 1).index, &song)) {
|
||||
@ -227,6 +265,7 @@ bool CueParser::UpdateSong(const CueEntry& entry, const QString& next_index, Son
|
||||
song->Init(entry.title, entry.PrettyArtist(),
|
||||
entry.album, beginning, end);
|
||||
song->set_albumartist(entry.album_artist);
|
||||
song->set_composer(entry.PrettyComposer());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -245,6 +284,7 @@ bool CueParser::UpdateLastSong(const CueEntry& entry, Song* song) const {
|
||||
song->set_artist(entry.PrettyArtist());
|
||||
song->set_album(entry.album);
|
||||
song->set_albumartist(entry.album_artist);
|
||||
song->set_composer(entry.PrettyComposer());
|
||||
|
||||
// we don't do anything with the end here because it's already set to
|
||||
// the end of the media file (if it exists)
|
||||
|
@ -34,6 +34,7 @@ class CueParser : public ParserBase {
|
||||
|
||||
static const char* kPerformer;
|
||||
static const char* kTitle;
|
||||
static const char* kSongWriter;
|
||||
static const char* kFile;
|
||||
static const char* kTrack;
|
||||
static const char* kIndex;
|
||||
@ -62,16 +63,22 @@ class CueParser : public ParserBase {
|
||||
QString album_artist;
|
||||
QString album;
|
||||
|
||||
QString composer;
|
||||
QString album_composer;
|
||||
|
||||
QString PrettyArtist() const { return artist.isEmpty() ? album_artist : artist; }
|
||||
QString PrettyComposer() const { return composer.isEmpty() ? album_composer : composer; }
|
||||
|
||||
CueEntry(QString& file, QString& index, QString& title, QString& artist,
|
||||
QString& album_artist, QString& album) {
|
||||
QString& album_artist, QString& album, QString& composer, QString& album_composer) {
|
||||
this->file = file;
|
||||
this->index = index;
|
||||
this->title = title;
|
||||
this->artist = artist;
|
||||
this->album_artist = album_artist;
|
||||
this->album = album;
|
||||
this->composer = composer;
|
||||
this->album_composer = album_composer;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -53,6 +53,7 @@ TEST_F(CueParserTest, ParsesASong) {
|
||||
ASSERT_EQ("Zucchero himself", first_song.albumartist());
|
||||
ASSERT_EQ("", first_song.album());
|
||||
ASSERT_EQ(1, first_song.beginning());
|
||||
ASSERT_EQ(1, first_song.track());
|
||||
}
|
||||
|
||||
TEST_F(CueParserTest, ParsesTwoSongs) {
|
||||
@ -66,19 +67,22 @@ TEST_F(CueParserTest, ParsesTwoSongs) {
|
||||
|
||||
// with the specified metadata
|
||||
Song first_song = song_list.at(0);
|
||||
Song second_song = song_list.at(1);
|
||||
|
||||
ASSERT_EQ("Un soffio caldo", first_song.title());
|
||||
ASSERT_EQ("Chocabeck", first_song.album());
|
||||
ASSERT_EQ("Zucchero himself", first_song.artist());
|
||||
ASSERT_EQ("Zucchero himself", first_song.albumartist());
|
||||
ASSERT_EQ(1, first_song.beginning());
|
||||
ASSERT_EQ((5 * 60 + 3) - 1, first_song.length());
|
||||
ASSERT_EQ(second_song.beginning() - first_song.beginning(), first_song.length());
|
||||
ASSERT_EQ(1, first_song.track());
|
||||
|
||||
Song second_song = song_list.at(1);
|
||||
ASSERT_EQ("Somewon Else's Tears", second_song.title());
|
||||
ASSERT_EQ("Chocabeck", second_song.album());
|
||||
ASSERT_EQ("Zucchero himself", second_song.artist());
|
||||
ASSERT_EQ("Zucchero himself", second_song.albumartist());
|
||||
ASSERT_EQ(5 * 60 + 3, second_song.beginning());
|
||||
ASSERT_EQ(2, second_song.track());
|
||||
}
|
||||
|
||||
TEST_F(CueParserTest, SkipsBrokenSongs) {
|
||||
@ -92,6 +96,8 @@ TEST_F(CueParserTest, SkipsBrokenSongs) {
|
||||
|
||||
// with the specified metadata
|
||||
Song first_song = song_list.at(0);
|
||||
Song second_song = song_list.at(1);
|
||||
|
||||
ASSERT_EQ("Un soffio caldo", first_song.title());
|
||||
ASSERT_EQ("Chocabeck", first_song.album());
|
||||
ASSERT_EQ("Zucchero himself", first_song.artist());
|
||||
@ -99,12 +105,183 @@ TEST_F(CueParserTest, SkipsBrokenSongs) {
|
||||
ASSERT_EQ(1, first_song.beginning());
|
||||
// includes the broken song too; this entry will span from it's
|
||||
// INDEX (beginning) to the end of the next correct song
|
||||
ASSERT_EQ((5 * 60) - 1, first_song.length());
|
||||
ASSERT_EQ(second_song.beginning() - first_song.beginning(), first_song.length());
|
||||
ASSERT_EQ(1, first_song.track());
|
||||
|
||||
Song second_song = song_list.at(1);
|
||||
ASSERT_EQ("Somewon Else's Tears", second_song.title());
|
||||
ASSERT_EQ("Chocabeck", second_song.album());
|
||||
ASSERT_EQ("Zucchero himself", second_song.artist());
|
||||
ASSERT_EQ("Zucchero himself", second_song.albumartist());
|
||||
ASSERT_EQ(5 * 60, second_song.beginning());
|
||||
ASSERT_EQ(2, second_song.track());
|
||||
}
|
||||
|
||||
TEST_F(CueParserTest, UsesAllMetadataInformation) {
|
||||
QFile file(":testdata/fullmetadata.cue");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
|
||||
SongList song_list = parser_.Load(&file, QDir(""));
|
||||
|
||||
// two songs
|
||||
ASSERT_EQ(2, song_list.size());
|
||||
|
||||
// with the specified metadata
|
||||
Song first_song = song_list.at(0);
|
||||
Song second_song = song_list.at(1);
|
||||
|
||||
ASSERT_TRUE(first_song.filename().endsWith("a_file.mp3"));
|
||||
ASSERT_EQ("Un soffio caldo", first_song.title());
|
||||
ASSERT_EQ("Album", first_song.album());
|
||||
ASSERT_EQ("Zucchero", first_song.artist());
|
||||
ASSERT_EQ("Zucchero himself", first_song.albumartist());
|
||||
ASSERT_EQ("Some guy", first_song.composer());
|
||||
ASSERT_EQ(1, first_song.beginning());
|
||||
ASSERT_EQ(second_song.beginning() - first_song.beginning(), first_song.length());
|
||||
ASSERT_EQ(1, first_song.track());
|
||||
|
||||
ASSERT_TRUE(second_song.filename().endsWith("a_file.mp3"));
|
||||
ASSERT_EQ("Hey you!", second_song.title());
|
||||
ASSERT_EQ("Album", second_song.album());
|
||||
ASSERT_EQ("Zucchero himself", second_song.artist());
|
||||
ASSERT_EQ("Zucchero himself", second_song.albumartist());
|
||||
ASSERT_EQ("Some other guy", second_song.composer());
|
||||
ASSERT_EQ(2, second_song.beginning());
|
||||
ASSERT_EQ(2, second_song.track());
|
||||
}
|
||||
|
||||
TEST_F(CueParserTest, AcceptsMultipleFileBasedCues) {
|
||||
QFile file(":testdata/manyfiles.cue");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
|
||||
SongList song_list = parser_.Load(&file, QDir(""));
|
||||
|
||||
// five songs
|
||||
ASSERT_EQ(5, song_list.size());
|
||||
|
||||
// with the specified metadata
|
||||
Song first_song = song_list.at(0);
|
||||
Song second_song = song_list.at(1);
|
||||
Song third_song = song_list.at(2);
|
||||
Song fourth_song = song_list.at(3);
|
||||
Song fifth_song = song_list.at(4);
|
||||
|
||||
ASSERT_TRUE(first_song.filename().endsWith("files/longer_one.mp3"));
|
||||
ASSERT_EQ("A1Song1", first_song.title());
|
||||
ASSERT_EQ("Artist One Album", first_song.album());
|
||||
ASSERT_EQ("Artist One", first_song.artist());
|
||||
ASSERT_EQ("Artist One", first_song.albumartist());
|
||||
ASSERT_EQ(1, first_song.beginning());
|
||||
ASSERT_EQ(second_song.beginning() - first_song.beginning(), first_song.length());
|
||||
ASSERT_EQ(-1, first_song.track());
|
||||
|
||||
ASSERT_TRUE(second_song.filename().endsWith("files/longer_one.mp3"));
|
||||
ASSERT_EQ("A1Song2", second_song.title());
|
||||
ASSERT_EQ("Artist One Album", second_song.album());
|
||||
ASSERT_EQ("Artist One", second_song.artist());
|
||||
ASSERT_EQ("Artist One", second_song.albumartist());
|
||||
ASSERT_EQ((5 * 60 + 3), second_song.beginning());
|
||||
ASSERT_EQ(-1, second_song.track());
|
||||
|
||||
ASSERT_TRUE(third_song.filename().endsWith("files/longer_two_p1.mp3"));
|
||||
ASSERT_EQ("A2P1Song1", third_song.title());
|
||||
ASSERT_EQ("Artist Two Album", third_song.album());
|
||||
ASSERT_EQ("Artist X", third_song.artist());
|
||||
ASSERT_EQ("Artist Two", third_song.albumartist());
|
||||
ASSERT_EQ(0, third_song.beginning());
|
||||
ASSERT_EQ(fourth_song.beginning() - third_song.beginning(), third_song.length());
|
||||
ASSERT_EQ(-1, third_song.track());
|
||||
|
||||
ASSERT_TRUE(fourth_song.filename().endsWith("files/longer_two_p1.mp3"));
|
||||
ASSERT_EQ("A2P1Song2", fourth_song.title());
|
||||
ASSERT_EQ("Artist Two Album", fourth_song.album());
|
||||
ASSERT_EQ("Artist Two", fourth_song.artist());
|
||||
ASSERT_EQ("Artist Two", fourth_song.albumartist());
|
||||
ASSERT_EQ(4 * 60, fourth_song.beginning());
|
||||
ASSERT_EQ(-1, fourth_song.track());
|
||||
|
||||
ASSERT_TRUE(fifth_song.filename().endsWith("files/longer_two_p2.mp3"));
|
||||
ASSERT_EQ("A2P2Song1", fifth_song.title());
|
||||
ASSERT_EQ("Artist Two Album", fifth_song.album());
|
||||
ASSERT_EQ("Artist Two", fifth_song.artist());
|
||||
ASSERT_EQ("Artist Two", fifth_song.albumartist());
|
||||
ASSERT_EQ(1, fifth_song.beginning());
|
||||
ASSERT_EQ(-1, fifth_song.track());
|
||||
}
|
||||
|
||||
TEST_F(CueParserTest, SkipsBrokenSongsInMultipleFileBasedCues) {
|
||||
QFile file(":testdata/manyfilesbroken.cue");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
|
||||
SongList song_list = parser_.Load(&file, QDir(""));
|
||||
|
||||
// four songs
|
||||
ASSERT_EQ(4, song_list.size());
|
||||
|
||||
// with the specified metadata
|
||||
Song first_song = song_list.at(0);
|
||||
Song second_song = song_list.at(1);
|
||||
Song third_song = song_list.at(2);
|
||||
Song fourth_song = song_list.at(3);
|
||||
|
||||
// A* - broken song in the middle
|
||||
ASSERT_TRUE(first_song.filename().endsWith("file1.mp3"));
|
||||
ASSERT_EQ("Artist One", first_song.artist());
|
||||
ASSERT_EQ("Artist One Album", first_song.album());
|
||||
ASSERT_EQ("A1", first_song.title());
|
||||
ASSERT_EQ(1, first_song.beginning());
|
||||
ASSERT_EQ(second_song.beginning() - first_song.beginning(), first_song.length());
|
||||
ASSERT_EQ(-1, first_song.track());
|
||||
|
||||
ASSERT_TRUE(second_song.filename().endsWith("file1.mp3"));
|
||||
ASSERT_EQ("Artist One", second_song.artist());
|
||||
ASSERT_EQ("Artist One Album", second_song.album());
|
||||
ASSERT_EQ("A3", second_song.title());
|
||||
ASSERT_EQ(60, second_song.beginning());
|
||||
ASSERT_EQ(-1, second_song.track());
|
||||
|
||||
// all B* songs are broken
|
||||
|
||||
// C* - broken song at the end
|
||||
ASSERT_TRUE(third_song.filename().endsWith("file3.mp3"));
|
||||
ASSERT_EQ("Artist Three", third_song.artist());
|
||||
ASSERT_EQ("Artist Three Album", third_song.album());
|
||||
ASSERT_EQ("C1", third_song.title());
|
||||
ASSERT_EQ(1, third_song.beginning());
|
||||
ASSERT_EQ(-1, third_song.track());
|
||||
|
||||
// D* - broken song at the beginning
|
||||
ASSERT_TRUE(fourth_song.filename().endsWith("file4.mp3"));
|
||||
ASSERT_EQ("Artist Four", fourth_song.artist());
|
||||
ASSERT_EQ("Artist Four Album", fourth_song.album());
|
||||
ASSERT_EQ("D2", fourth_song.title());
|
||||
ASSERT_EQ(61, fourth_song.beginning());
|
||||
ASSERT_EQ(-1, fourth_song.track());
|
||||
}
|
||||
|
||||
TEST_F(CueParserTest, SkipsDataFiles) {
|
||||
QFile file(":testdata/withdatafiles.cue");
|
||||
file.open(QIODevice::ReadOnly);
|
||||
|
||||
SongList song_list = parser_.Load(&file, QDir(""));
|
||||
|
||||
// two songs
|
||||
ASSERT_EQ(2, song_list.size());
|
||||
|
||||
// with the specified metadata
|
||||
Song first_song = song_list.at(0);
|
||||
Song second_song = song_list.at(1);
|
||||
|
||||
ASSERT_TRUE(first_song.filename().endsWith("file1.mp3"));
|
||||
ASSERT_EQ("Artist One", first_song.artist());
|
||||
ASSERT_EQ("Artist One Album", first_song.album());
|
||||
ASSERT_EQ("A1", first_song.title());
|
||||
ASSERT_EQ(1, first_song.beginning());
|
||||
ASSERT_EQ(-1, first_song.track());
|
||||
|
||||
ASSERT_TRUE(second_song.filename().endsWith("file4.mp3"));
|
||||
ASSERT_EQ("Artist Four", second_song.artist());
|
||||
ASSERT_EQ("Artist Four Album", second_song.album());
|
||||
ASSERT_EQ("D1", second_song.title());
|
||||
ASSERT_EQ(61, second_song.beginning());
|
||||
ASSERT_EQ(-1, second_song.track());
|
||||
}
|
||||
|
13
tests/data/fullmetadata.cue
Normal file
13
tests/data/fullmetadata.cue
Normal file
@ -0,0 +1,13 @@
|
||||
FILE a_file.mp3 WAVE
|
||||
SONGWRITER "Some guy"
|
||||
TITLE "Album"
|
||||
PERFORMER "Zucchero himself"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "Un soffio caldo"
|
||||
PERFORMER Zucchero
|
||||
INDEX 00 00:01:00
|
||||
INDEX 01 00:01:00
|
||||
TRACK 02 AUDIO
|
||||
TITLE "Hey you!"
|
||||
SONGWRITER "Some other guy"
|
||||
INDEX 05 00:02:00
|
25
tests/data/manyfiles.cue
Normal file
25
tests/data/manyfiles.cue
Normal file
@ -0,0 +1,25 @@
|
||||
FILE files/longer_one.mp3 WAVE
|
||||
PERFORMER "Artist One"
|
||||
TITLE "Artist One Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "A1Song1"
|
||||
INDEX 01 00:01:00
|
||||
TRACK 02 AUDIO
|
||||
TITLE "A1Song2"
|
||||
INDEX 01 05:03:68
|
||||
FILE files/longer_two_p1.mp3 WAVE
|
||||
PERFORMER "Artist Two"
|
||||
TITLE "Artist Two Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "A2P1Song1"
|
||||
PERFORMER "Artist X"
|
||||
INDEX 01 00:00:00
|
||||
TRACK 02 AUDIO
|
||||
TITLE "A2P1Song2"
|
||||
INDEX 01 04:00:00
|
||||
FILE files/longer_two_p2.mp3 WAVE
|
||||
PERFORMER "Artist Two"
|
||||
TITLE "Artist Two Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "A2P2Song1"
|
||||
INDEX 01 00:01:00
|
33
tests/data/manyfilesbroken.cue
Normal file
33
tests/data/manyfilesbroken.cue
Normal file
@ -0,0 +1,33 @@
|
||||
FILE file1.mp3 WAVE
|
||||
PERFORMER "Artist One"
|
||||
TITLE "Artist One Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "A1"
|
||||
INDEX 01 00:01:00
|
||||
TRACK 02 AUDIO
|
||||
TITLE "A2"
|
||||
TRACK 03 AUDIO
|
||||
TITLE "A3"
|
||||
INDEX 01 01:00:00
|
||||
FILE file2.mp3 WAVE
|
||||
PERFORMER "Artist Two"
|
||||
TITLE "Artist Two Album"
|
||||
TRACK 01 CDG
|
||||
TITLE "B1"
|
||||
INDEX 00 00:01:00
|
||||
FILE file3.mp3 WAVE
|
||||
PERFORMER "Artist Three"
|
||||
TITLE "Artist Three Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "C1"
|
||||
INDEX 00 00:01:00
|
||||
TRACK 02 AUDIO
|
||||
TITLE "C2"
|
||||
FILE file4.mp3 WAVE
|
||||
PERFORMER "Artist Four"
|
||||
TITLE "Artist Four Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "D1"
|
||||
TRACK 02 AUDIO
|
||||
TITLE "D2"
|
||||
INDEX 00 01:01:00
|
@ -8,21 +8,25 @@
|
||||
<file>beep.wma</file>
|
||||
<file>beep.m4a</file>
|
||||
<file>brokensong.cue</file>
|
||||
<file>onesong.cue</file>
|
||||
<file>twosongs.cue</file>
|
||||
<file>pls_one.pls</file>
|
||||
<file>pls_somafm.pls</file>
|
||||
<file>test.m3u</file>
|
||||
<file>test.xspf</file>
|
||||
<file>test.asx</file>
|
||||
<file>secretagent.asx</file>
|
||||
<file>secretagent.pls</file>
|
||||
<file>test.asxini</file>
|
||||
<file>fmpsplaycount.mp3</file>
|
||||
<file>fmpsplaycountboth.mp3</file>
|
||||
<file>fmpsplaycountuser.mp3</file>
|
||||
<file>fmpsrating.mp3</file>
|
||||
<file>fmpsratingboth.mp3</file>
|
||||
<file>fmpsratinguser.mp3</file>
|
||||
<file>fullmetadata.cue</file>
|
||||
<file>manyfiles.cue</file>
|
||||
<file>manyfilesbroken.cue</file>
|
||||
<file>onesong.cue</file>
|
||||
<file>pls_one.pls</file>
|
||||
<file>pls_somafm.pls</file>
|
||||
<file>secretagent.asx</file>
|
||||
<file>secretagent.pls</file>
|
||||
<file>test.m3u</file>
|
||||
<file>test.xspf</file>
|
||||
<file>test.asx</file>
|
||||
<file>test.asxini</file>
|
||||
<file>twosongs.cue</file>
|
||||
<file>withdatafiles.cue</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
28
tests/data/withdatafiles.cue
Normal file
28
tests/data/withdatafiles.cue
Normal file
@ -0,0 +1,28 @@
|
||||
FILE file1.mp3
|
||||
PERFORMER "Artist One"
|
||||
TITLE "Artist One Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "A1"
|
||||
INDEX 01 00:01:00
|
||||
|
||||
FILE file2.mp3 BINARY
|
||||
PERFORMER "Artist Two"
|
||||
TITLE "Artist Two Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "B1"
|
||||
INDEX 00 00:01:00
|
||||
|
||||
FILE file3.mp3 MOTOROLA
|
||||
PERFORMER "Artist Three"
|
||||
TITLE "Artist Three Album"
|
||||
|
||||
TRACK 01 AUDIO
|
||||
TITLE "C1"
|
||||
INDEX 00 00:01:00
|
||||
|
||||
FILE file4.mp3 MP3
|
||||
PERFORMER "Artist Four"
|
||||
TITLE "Artist Four Album"
|
||||
TRACK 01 AUDIO
|
||||
TITLE "D1"
|
||||
INDEX 00 01:01:00
|
Loading…
x
Reference in New Issue
Block a user