finalized the support for loading .cue based media using 'files' tab or drag and drop from the system's file browser

use FILE's PERFORMER as albumartist
This commit is contained in:
Paweł Bara 2011-01-03 23:36:10 +00:00
parent 34d496aadc
commit 59378166b4
7 changed files with 85 additions and 10 deletions

View File

@ -20,6 +20,7 @@
#include "library/librarybackend.h"
#include "library/sqlrow.h"
#include "playlistparsers/parserbase.h"
#include "playlistparsers/cueparser.h"
#include "playlistparsers/playlistparser.h"
#include "radio/fixlastfm.h"
@ -39,6 +40,7 @@ SongLoader::SongLoader(LibraryBackendInterface* library, QObject *parent)
: QObject(parent),
timeout_timer_(new QTimer(this)),
playlist_parser_(new PlaylistParser(library, this)),
cue_parser_(new CueParser(library, this)),
timeout_(kDefaultTimeout),
state_(WaitingForType),
success_(false),
@ -130,17 +132,46 @@ SongLoader::Result SongLoader::LoadLocal(const QString& filename, bool block,
// Not a playlist, so just assume it's a song
QFileInfo info(filename);
LibraryQuery query;
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
query.AddWhere("filename", info.canonicalFilePath());
Song song;
SongList song_list;
if (library_->ExecQuery(&query) && query.Next()) {
song.InitFromQuery(query);
// we may have many results when the file has many sections
do {
Song song;
song.InitFromQuery(query);
song_list << song;
} while(query.Next());
} else {
song.InitFromFile(filename, -1);
QString matching_cue = filename.section('.', 0, -2) + ".cue";
// it's a cue - create virtual tracks
if(QFile::exists(matching_cue)) {
QFile cue(matching_cue);
cue.open(QIODevice::ReadOnly);
song_list = cue_parser_->Load(&cue, QDir(filename.section('/', 0, -2)));
// it's a normal media file
} else {
Song song;
song.InitFromFile(filename, -1);
song_list << song;
}
}
if (song.is_valid())
songs_ << song;
foreach(const Song& song, song_list) {
if (song.is_valid())
songs_ << song;
}
return Success;
}

View File

@ -27,6 +27,7 @@
#include <gst/gst.h>
class CueParser;
class LibraryBackendInterface;
class ParserBase;
class PlaylistParser;
@ -97,6 +98,7 @@ private:
QTimer* timeout_timer_;
PlaylistParser* playlist_parser_;
CueParser* cue_parser_;
// For async loads
int timeout_;

View File

@ -23,7 +23,7 @@
#include <QTextStream>
#include <QtDebug>
const char* CueParser::kFileLineRegExp = "([^ \t\r\n]+)\\s+(?:\"([^\"]+)\"|([^ \t\r\n]+))\\s*(?:\"([^\"]+)\"|([^ \t\r\n]+))?";
const char* CueParser::kFileLineRegExp = "(\\S+)\\s+(?:\"([^\"]+)\"|(\\S+))\\s*(?:\"([^\"]+)\"|(\\S+))?";
const char* CueParser::kIndexRegExp = "(\\d{2}):(\\d{2}):(\\d{2})";
const char* CueParser::kPerformer = "performer";
@ -33,9 +33,6 @@ const char* CueParser::kTrack = "track";
const char* CueParser::kIndex = "index";
const char* CueParser::kAudioTrackType = "audio";
// TODO: if some song misses it's next one (because the next one was somehow
// broken), we need to discard the song too (can't really determine where it
// ends
// TODO: utf and regexps (check on Zucchero - there's something wrong)
CueParser::CueParser(LibraryBackendInterface* library, QObject* parent)
@ -228,6 +225,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);
return true;
}
@ -245,6 +243,7 @@ bool CueParser::UpdateLastSong(const CueEntry& entry, Song* song) const {
song->set_title(entry.title);
song->set_artist(entry.PrettyArtist());
song->set_album(entry.album);
song->set_albumartist(entry.album_artist);
// we don't do anything with the end here because it's already set to
// the end of the media file (if it exists)

View File

@ -50,6 +50,7 @@ TEST_F(CueParserTest, ParsesASong) {
Song first_song = song_list.at(0);
ASSERT_EQ("Un soffio caldo", first_song.title());
ASSERT_EQ("Zucchero", first_song.artist());
ASSERT_EQ("Zucchero himself", first_song.albumartist());
ASSERT_EQ("", first_song.album());
ASSERT_EQ(1, first_song.beginning());
}
@ -68,6 +69,7 @@ TEST_F(CueParserTest, ParsesTwoSongs) {
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());
@ -75,5 +77,34 @@ TEST_F(CueParserTest, ParsesTwoSongs) {
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());
}
TEST_F(CueParserTest, SkipsBrokenSongs) {
QFile file(":testdata/brokensong.cue");
file.open(QIODevice::ReadOnly);
SongList song_list = parser_.Load(&file, QDir(""));
// two songs (the broken one is not in the list)
ASSERT_EQ(2, song_list.size());
// with the specified metadata
Song first_song = song_list.at(0);
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());
// 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());
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());
}

11
tests/data/brokensong.cue Normal file
View File

@ -0,0 +1,11 @@
PERFORMER "Zucchero himself"
TITLE "Chocabeck"
FILE files/longer.mp3 WAVE
TRACK 01 AUDIO
TITLE "Un soffio caldo"
INDEX 01 00:01:00
TRACK 02 AUDIO
TITLE "No index - broken"
TRACK 02 AUDIO
TITLE "Somewon Else's Tears"
INDEX 01 05:00:00

View File

@ -1,4 +1,4 @@
PERFORMER "Zucchero"
PERFORMER "Zucchero himself"
FILE "file.mp3" WAVE
TRACK 01 AUDIO
TITLE "Un soffio caldo"

View File

@ -7,6 +7,7 @@
<file>beep.wav</file>
<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>