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