Improve error handling of playback process
This commit is contained in:
parent
6f08458f63
commit
7e43808b4d
6 changed files with 75 additions and 10 deletions
|
@ -14,7 +14,7 @@ void CFile::open(const char *fname) {
|
|||
name = fname;
|
||||
file = fopen(fname, "rb");
|
||||
if (file == NULL) {
|
||||
throw std::exception();
|
||||
throw NotFoundException(fname);
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
len = ftell(file);
|
||||
|
|
|
@ -9,15 +9,54 @@
|
|||
#include <stdlib.h>
|
||||
#include <SDL.h>
|
||||
#include <vector>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
extern "C" {
|
||||
#include <vgmstream.h>
|
||||
}
|
||||
#include "log.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
enum class SeekType {
|
||||
SET,
|
||||
CUR,
|
||||
END
|
||||
};
|
||||
class CustomException : public std::exception {
|
||||
const char *message;
|
||||
protected:
|
||||
void clear_message(bool free_message = true) {
|
||||
if (free_message && this->message != nullptr) {
|
||||
free((void*)this->message);
|
||||
}
|
||||
this->message = nullptr;
|
||||
}
|
||||
public:
|
||||
CustomException() {
|
||||
clear_message(false);
|
||||
}
|
||||
CustomException(std::string message) : CustomException() {
|
||||
set_message(message);
|
||||
}
|
||||
void set_message(std::string message) {
|
||||
clear_message();
|
||||
this->message = strdup(message.c_str());
|
||||
}
|
||||
const char *what() const throw() {
|
||||
return this->message;
|
||||
}
|
||||
~CustomException() {
|
||||
clear_message();
|
||||
}
|
||||
};
|
||||
class NotFoundException : public CustomException {
|
||||
public:
|
||||
NotFoundException(std::string file) : CustomException() {
|
||||
set_message(fmt::format("File not found: {0}", file));
|
||||
}
|
||||
NotFoundException(const char *file) : NotFoundException(std::string(file)) { }
|
||||
};
|
||||
|
||||
class File {
|
||||
protected:
|
||||
size_t len;
|
||||
|
|
18
playback.cpp
18
playback.cpp
|
@ -137,9 +137,14 @@ void PlaybackInstance::Load(const char *file, int idx) {
|
|||
SDL_LockAudioDevice(device);
|
||||
playback_ready.store(false);
|
||||
if (process != nullptr) delete process;
|
||||
process = new PlaybackProcess(file, idx);
|
||||
try {
|
||||
process = new PlaybackProcess(file, idx);
|
||||
} catch (std::exception e) {
|
||||
ERROR.writefln("Exception caught when creating process: %s", e.what());
|
||||
process = nullptr;
|
||||
}
|
||||
length = 0.0;
|
||||
if (process->process_running()) {
|
||||
if (process != nullptr && process->process_running()) {
|
||||
length = process->get_length();
|
||||
auto backend_spec_proxy = process->get_audio_spec();
|
||||
memset(&backend_spec, 0, sizeof(backend_spec));
|
||||
|
@ -186,8 +191,7 @@ void PlaybackInstance::Load(const char *file, int idx) {
|
|||
load_finished.store(true);
|
||||
this->process->set_position(0.0);
|
||||
} else {
|
||||
ERROR.writeln("Failed to detect valid playback backend for file!");
|
||||
set_error("Failed to detect valid backend for file.");
|
||||
set_error("Failed to create playback backend.");
|
||||
set_signal(PlaybackSignalErrorOccurred);
|
||||
delete process;
|
||||
process = nullptr;
|
||||
|
@ -387,7 +391,11 @@ void PlaybackInstance::LoopFunction() {
|
|||
}
|
||||
flag_mutex.unlock();
|
||||
}
|
||||
position = process->get_position();
|
||||
if (process) {
|
||||
position = process->get_position();
|
||||
} else {
|
||||
position = 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
void PlaybackInstance::DeinitLoopFunction() {
|
||||
|
|
|
@ -291,6 +291,7 @@ ResetResponse PlaybackProcessServiceImpl::Reset(const ResetProperty *request) {
|
|||
return response;
|
||||
}
|
||||
MaybeError PlaybackProcessServiceImpl::Quit(const QuitCmd *request) {
|
||||
if (process == nullptr) return MaybeError();
|
||||
process->done = true;
|
||||
cur_backend_lock.get_unsafe()->cleanup();
|
||||
return MaybeError();
|
||||
|
@ -302,6 +303,15 @@ MaybeError PlaybackProcessServiceImpl::Init(const InitCommand *cmd) {
|
|||
render_ptr.lock().set(new DynPtr(), true);
|
||||
lock.clear();
|
||||
auto filename = cmd->filename();
|
||||
|
||||
if (!std::filesystem::exists(filename)) {
|
||||
ErrorResponse *maybe_error = response->mutable_err();
|
||||
maybe_error->set_desc("File not found");
|
||||
maybe_error->set_id("not_found");
|
||||
maybe_error->set_fatal(true);
|
||||
process->done = true;
|
||||
return ret;
|
||||
}
|
||||
auto idx = cmd->idx();
|
||||
for (auto &backend : PlaybackBackendHelper()) {
|
||||
DEBUG.writefln("Trying backend: %s", backend.second->get_name().c_str());
|
||||
|
@ -317,11 +327,10 @@ MaybeError PlaybackProcessServiceImpl::Init(const InitCommand *cmd) {
|
|||
break;
|
||||
}
|
||||
if (!cur_backend_lock.has_value()) {
|
||||
ErrorResponse *maybe_error = new ErrorResponse();
|
||||
ErrorResponse *maybe_error = response->mutable_err();
|
||||
maybe_error->set_desc("Couldn't find a backend.");
|
||||
maybe_error->set_id("no_backend_for_file");
|
||||
maybe_error->set_fatal(true);
|
||||
response->set_allocated_err(maybe_error);
|
||||
process->done = true;
|
||||
DEBUG.writefln("Couldn't find any backend.");
|
||||
return ret;
|
||||
|
@ -401,7 +410,11 @@ PlaybackProcess::PlaybackProcess(std::string filename, int idx) {
|
|||
call.mutable_init()->CopyFrom(cmd);
|
||||
RPCResponse response = SendCommand(&call);
|
||||
if (response.has_err()) {
|
||||
throw std::exception();
|
||||
this->init_failed = true;
|
||||
delete other_process;
|
||||
other_process = nullptr;
|
||||
auto err = response.err();
|
||||
throw CustomException(err.has_desc() ? err.desc() : err.id());
|
||||
}
|
||||
}
|
||||
bool PlaybackProcess::process_running() {
|
||||
|
@ -577,6 +590,10 @@ AudioSpec *PlaybackProcess::get_audio_spec() {
|
|||
return get_property_value<AudioSpec>(PropertyId::SpecProperty);
|
||||
}
|
||||
PlaybackProcess::~PlaybackProcess() {
|
||||
if (init_failed || other_process == nullptr) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
QuitCmd quit_cmd;
|
||||
RPCCall call;
|
||||
call.mutable_quit()->CopyFrom(quit_cmd);
|
||||
|
|
|
@ -45,6 +45,7 @@ class PlaybackProcess {
|
|||
PlaybackProcess *other_process = nullptr;
|
||||
PlaybackProcessServiceImpl impl;
|
||||
int pid;
|
||||
bool init_failed = false;
|
||||
std::mutex start_mutex;
|
||||
std::condition_variable started;
|
||||
bool is_playback_process = false;
|
||||
|
|
Loading…
Reference in a new issue