Fixed a race condition in GaplessTransport where the recently created

player may get destroyed before the playback bootstrap finishes, leading
to a crash.

Also fixed a bug in LruDiskCache entry parsing that could result in
playback failing.
This commit is contained in:
casey langen 2020-10-10 22:05:30 -07:00
parent 346affb027
commit ccc4040213
2 changed files with 21 additions and 32 deletions

View File

@ -120,20 +120,20 @@ void GaplessTransport::StartWithPlayer(Player* newPlayer, StartMode mode) {
this->nextPlayer = nullptr; this->nextPlayer = nullptr;
this->activePlayer = newPlayer; this->activePlayer = newPlayer;
}
/* first argument suppresses the "Stop" event from getting triggered, /* first argument suppresses the "Stop" event from getting triggered,
the second param is used for gapless playback -- we won't stop the output the second param is used for gapless playback -- we won't stop the output
and will allow pending buffers to finish if we're not automatically and will allow pending buffers to finish if we're not automatically
playing the next track. note we do this outside of critical section so playing the next track. note we do this outside of critical section so
outputs *can* stop buffers immediately, and not to worry about causing a outputs *can* stop buffers immediately, and not to worry about causing a
deadlock. */ deadlock. */
this->StopInternal(true, !playingNext, newPlayer); this->StopInternal(true, !playingNext, newPlayer);
this->SetNextCanStart(false); this->SetNextCanStart(false);
this->output->Resume(); this->output->Resume();
if (mode == StartMode::Immediate) { if (mode == StartMode::Immediate) {
newPlayer->Play(); newPlayer->Play();
}
} }
this->RaiseStreamEvent(StreamScheduled, newPlayer); this->RaiseStreamEvent(StreamScheduled, newPlayer);

View File

@ -53,10 +53,9 @@ static std::string tempFilename(const std::string& root, size_t id) {
return root + "/" + PREFIX + "_" + std::to_string(id) + TEMP_EXTENSION; return root + "/" + PREFIX + "_" + std::to_string(id) + TEMP_EXTENSION;
} }
static std::string finalFilename(const std::string& root, size_t id, std::string extension) { static std::string finalFilename(const std::string& root, size_t id, std::string type) {
al::replace_all(extension, "/", "-"); al::replace_all(type, "/", "-");
al::replace_all(extension, ".", ""); return root + "/" + PREFIX + "_" + std::to_string(id) + "_" + type;
return root + "/" + PREFIX + "_" + std::to_string(id) + "." + extension;
} }
static bool isTemp(const fs::path& path) { static bool isTemp(const fs::path& path) {
@ -146,27 +145,17 @@ void LruDiskCache::Purge() {
} }
LruDiskCache::EntryPtr LruDiskCache::Parse(const fs::path& path) { LruDiskCache::EntryPtr LruDiskCache::Parse(const fs::path& path) {
std::string fn = path.stem().string(); /* no extension */ std::string fn = path.string();
std::string ext = path.extension().string();
if (ext.size()) {
if (ext.at(0) == '.') {
ext = ext.substr(1);
}
al::replace_all(ext, "-", "/");
}
std::vector<std::string> parts; std::vector<std::string> parts;
boost::split(parts, fn, boost::is_any_of("_")); boost::split(parts, fn, boost::is_any_of("_"));
if (parts.size() == 3 && parts[0] == PREFIX) {
if (parts.size() == 2 && parts.at(0) == PREFIX) {
try { try {
auto entry = std::shared_ptr<Entry>(new Entry()); auto entry = std::shared_ptr<Entry>(new Entry());
entry->id = std::stoull(parts.at(1).c_str()); entry->id = std::stoull(parts[1].c_str());
entry->path = path.string(); entry->path = fn;
entry->type = ext; entry->type = parts[2];
entry->time = fs::last_write_time(path); entry->time = fs::last_write_time(path);
al::replace_all(entry->type, "-", "/");
return entry; return entry;
} }
catch (...) { catch (...) {