Some minor bugfixes
This commit is contained in:
parent
07958ec36b
commit
438b2ad1c6
@ -1,7 +1,8 @@
|
||||
import * as native from "tc-native/connection";
|
||||
import * as path from "path";
|
||||
import {DownloadKey, DownloadTransfer, UploadKey, UploadTransfer} from "tc-shared/FileManager";
|
||||
import {DownloadKey, DownloadTransfer, UploadKey, UploadTransfer} from "tc-shared/file/FileManager";
|
||||
import {base64_encode_ab, str2ab8} from "tc-shared/utils/buffers";
|
||||
import {set_transfer_provider, TransferKey, TransferProvider} from "tc-shared/file/FileManager";
|
||||
|
||||
class NativeFileDownload implements DownloadTransfer {
|
||||
readonly key: DownloadKey;
|
||||
@ -169,12 +170,12 @@ class NativeFileUpload implements UploadTransfer {
|
||||
}
|
||||
}
|
||||
|
||||
set_transfer_provider(new class implements TransferProvider {
|
||||
spawn_upload_transfer(key: TransferKey): UploadTransfer {
|
||||
return new NativeFileUpload(key);
|
||||
}
|
||||
|
||||
export function spawn_download_transfer(key: DownloadKey) : DownloadTransfer {
|
||||
return new NativeFileDownload(key);
|
||||
}
|
||||
|
||||
|
||||
export function spawn_upload_transfer(key: UploadKey) : UploadTransfer {
|
||||
return new NativeFileUpload(key);
|
||||
}
|
||||
spawn_download_transfer(key: TransferKey): DownloadTransfer {
|
||||
return new NativeFileDownload(key);
|
||||
}
|
||||
});
|
@ -150,6 +150,7 @@ loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||
require("./context-menu");
|
||||
require("./app_backend");
|
||||
require("./icon-helper").initialize();
|
||||
require("./connection/FileTransfer");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
window.displayCriticalError("Failed to load native extensions: " + error);
|
||||
|
@ -643,6 +643,9 @@ void ServerConnection::close_connection() {
|
||||
void ServerConnection::execute_tick() {
|
||||
if(this->protocol_handler)
|
||||
this->protocol_handler->execute_tick();
|
||||
|
||||
if(auto vc{this->voice_connection}; vc)
|
||||
vc->execute_tick();
|
||||
}
|
||||
|
||||
void ServerConnection::_execute_callback_commands() {
|
||||
|
@ -208,7 +208,7 @@ VoiceClientWrap::VoiceClientWrap(const std::shared_ptr<VoiceClient>& client) : _
|
||||
|
||||
VoiceClientWrap::~VoiceClientWrap() {}
|
||||
|
||||
VoiceClient::VoiceClient(const std::shared_ptr<VoiceConnection>&, uint16_t client_id) : _client_id(client_id) {
|
||||
VoiceClient::VoiceClient(const std::shared_ptr<VoiceConnection>&, uint16_t client_id) : client_id_(client_id) {
|
||||
this->execute_lock_timeout = std::chrono::microseconds{500};
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ VoiceClient::~VoiceClient() {
|
||||
if(v8::Isolate::GetCurrent())
|
||||
this->finalize_js_object();
|
||||
else {
|
||||
assert(this->_js_handle.IsEmpty());
|
||||
assert(this->js_handle_.IsEmpty());
|
||||
}
|
||||
|
||||
this->cancel_replay(); /* cleanup all buffers */
|
||||
@ -227,7 +227,7 @@ VoiceClient::~VoiceClient() {
|
||||
}
|
||||
|
||||
void VoiceClient::initialize() {
|
||||
auto weak_this = this->_ref;
|
||||
auto weak_this = this->ref_;
|
||||
|
||||
audio::initialize([weak_this]{
|
||||
auto client = weak_this.lock();
|
||||
@ -241,15 +241,15 @@ void VoiceClient::initialize() {
|
||||
|
||||
const auto client_ptr = &*client;
|
||||
client->output_source->on_underflow = [client_ptr](size_t sample_count){ /* this callback will never be called when the client has been deallocated */
|
||||
if(client_ptr->_state == state::stopping)
|
||||
if(client_ptr->state_ == state::stopping)
|
||||
client_ptr->set_state(state::stopped);
|
||||
else if(client_ptr->_state != state::stopped) {
|
||||
if(client_ptr->_last_received_packet + chrono::seconds(1) < chrono::system_clock::now()) {
|
||||
else if(client_ptr->state_ != state::stopped) {
|
||||
if(client_ptr->_last_received_packet + chrono::seconds{1} < chrono::system_clock::now()) {
|
||||
client_ptr->set_state(state::stopped);
|
||||
log_warn(category::audio, tr("Client {} has a audio buffer underflow for {} samples and not received any data for one second. Stopping replay."), client_ptr->_client_id, sample_count);
|
||||
log_warn(category::audio, tr("Client {} has a audio buffer underflow for {} samples and not received any data for one second. Stopping replay."), client_ptr->client_id_, sample_count);
|
||||
} else {
|
||||
if(client_ptr->_state != state::buffering) {
|
||||
log_warn(category::audio, tr("Client {} has a audio buffer underflow for {} samples. Buffer again."), client_ptr->_client_id, sample_count);
|
||||
if(client_ptr->state_ != state::buffering) {
|
||||
log_warn(category::audio, tr("Client {} has a audio buffer underflow for {} samples. Buffer again."), client_ptr->client_id_, sample_count);
|
||||
client_ptr->set_state(state::buffering);
|
||||
}
|
||||
|
||||
@ -260,13 +260,20 @@ void VoiceClient::initialize() {
|
||||
return false;
|
||||
};
|
||||
client->output_source->on_overflow = [client_ptr](size_t count){
|
||||
log_warn(category::audio, tr("Client {} has a audio buffer overflow of {}."), client_ptr->_client_id, count);
|
||||
log_warn(category::audio, tr("Client {} has a audio buffer overflow of {}."), client_ptr->client_id_, count);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
void VoiceClient::execute_tick() {
|
||||
if(this->state_ == state::buffering && this->_last_received_packet + chrono::milliseconds{250} < chrono::system_clock::now()) {
|
||||
this->set_state(state::stopped);
|
||||
log_debug(category::audio, tr("Audio stop packet for client {} seems to be lost. Stopping playback."), this->client_id_);
|
||||
}
|
||||
}
|
||||
|
||||
void VoiceClient::initialize_js_object() {
|
||||
if(!this->_js_handle.IsEmpty())
|
||||
if(!this->js_handle_.IsEmpty())
|
||||
return;
|
||||
|
||||
auto object_wrap = new VoiceClientWrap(this->ref());
|
||||
@ -278,11 +285,11 @@ void VoiceClient::initialize_js_object() {
|
||||
return;
|
||||
}
|
||||
|
||||
this->_js_handle.Reset(Nan::GetCurrentContext()->GetIsolate(), object);
|
||||
this->js_handle_.Reset(Nan::GetCurrentContext()->GetIsolate(), object);
|
||||
}
|
||||
|
||||
void VoiceClient::finalize_js_object() {
|
||||
this->_js_handle.Reset();
|
||||
this->js_handle_.Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -328,7 +335,7 @@ void VoiceClient::process_packet(uint16_t packet_id, const pipes::buffer_view& b
|
||||
}
|
||||
#endif
|
||||
if(codec < 0 || codec > this->codec.size()) {
|
||||
log_warn(category::voice_connection, tr("Received voice packet from client {} with unknown codec ({})"), this->_client_id, codec);
|
||||
log_warn(category::voice_connection, tr("Received voice packet from client {} with unknown codec ({})"), this->client_id_, codec);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -396,7 +403,7 @@ void VoiceClient::process_packet(uint16_t packet_id, const pipes::buffer_view& b
|
||||
}
|
||||
|
||||
void VoiceClient::cancel_replay() {
|
||||
log_trace(category::voice_connection, tr("Cancel replay for client {}"), this->_client_id);
|
||||
log_trace(category::voice_connection, tr("Cancel replay for client {}"), this->client_id_);
|
||||
|
||||
if(output_source) this->output_source->clear();
|
||||
this->set_state(state::stopped);
|
||||
@ -547,14 +554,14 @@ void VoiceClient::event_execute(const std::chrono::system_clock::time_point &sch
|
||||
while(replay_head) {
|
||||
if(replay_head->buffer.empty()) {
|
||||
this->set_state(state::stopping);
|
||||
log_debug(category::voice_connection, tr("Client {} send a stop signal. Flushing stream and stopping"), this->_client_id);
|
||||
log_debug(category::voice_connection, tr("Client {} send a stop signal. Flushing stream and stopping"), this->client_id_);
|
||||
} else {
|
||||
auto lost_packets = packet_id_diff(local_last_pid, replay_head->packet_id) - 1;
|
||||
if(lost_packets > 10) {
|
||||
log_debug(category::voice_connection, tr("Client {} seems to be missing {} packets in stream ({} to {}). Resetting decoder."), this->_client_id, lost_packets, local_last_pid, replay_head->packet_id);
|
||||
log_debug(category::voice_connection, tr("Client {} seems to be missing {} packets in stream ({} to {}). Resetting decoder."), this->client_id_, lost_packets, local_last_pid, replay_head->packet_id);
|
||||
replay_head->reset_decoder = true;
|
||||
} else if(lost_packets > 0) {
|
||||
log_debug(category::voice_connection, tr("Client {} seems to be missing {} packets in stream. FEC decoding it."), this->_client_id, lost_packets);
|
||||
log_debug(category::voice_connection, tr("Client {} seems to be missing {} packets in stream. FEC decoding it."), this->client_id_, lost_packets);
|
||||
/*
|
||||
if(audio_codec.converter->decode_lost(error, lost_packets))
|
||||
log_warn(category::audio, tr("Failed to decode lost packets for client {}: {}"), this->_client_id, error);
|
||||
@ -564,7 +571,7 @@ void VoiceClient::event_execute(const std::chrono::system_clock::time_point &sch
|
||||
this->output_source->enqueue_samples(decoded->sample_data, decoded->sample_size);
|
||||
}
|
||||
|
||||
const auto is_new_audio_stream = this->_state != state::buffering && this->_state != state::playing;
|
||||
const auto is_new_audio_stream = this->state_ != state::buffering && this->state_ != state::playing;
|
||||
if(replay_head->reset_decoder || is_new_audio_stream) {
|
||||
audio_codec.converter->reset_decoder();
|
||||
replay_head->reset_decoder = false;
|
||||
@ -595,10 +602,10 @@ void VoiceClient::event_execute(const std::chrono::system_clock::time_point &sch
|
||||
//TODO: Use statically allocated buffer?
|
||||
auto decoded = this->decode_buffer(audio_codec.codec, replay_head->buffer, false);
|
||||
if(!decoded) {
|
||||
log_warn(category::audio, tr("Failed to decode buffer for client {} (nullptr). Dropping buffer."), this->_client_id, error);
|
||||
log_warn(category::audio, tr("Failed to decode buffer for client {} (nullptr). Dropping buffer."), this->client_id_, error);
|
||||
} else {
|
||||
if(is_new_audio_stream) {
|
||||
log_warn(category::audio, tr("New audio chunk for client {}"), this->_client_id);
|
||||
log_warn(category::audio, tr("New audio chunk for client {}"), this->client_id_);
|
||||
|
||||
//this->output_source->enqueue_silence((size_t) ceil(0.0075f * (float) this->output_source->sample_rate)); /* enqueue 7.5ms silence so we give the next packet a chance to be send */
|
||||
}
|
||||
@ -640,7 +647,7 @@ void VoiceClient::initialize_code(const codec::value &audio_codec) {
|
||||
|
||||
auto info = codec::get_info(audio_codec);
|
||||
if(!info || !info->supported) {
|
||||
log_warn(category::voice_connection, tr("Failed to initialized codec {} for client {}. Codec is not supported"), audio_codec, this->_client_id);
|
||||
log_warn(category::voice_connection, tr("Failed to initialized codec {} for client {}. Codec is not supported"), audio_codec, this->client_id_);
|
||||
codec_data.state = AudioCodec::State::UNSUPPORTED;
|
||||
return;
|
||||
}
|
||||
@ -648,18 +655,18 @@ void VoiceClient::initialize_code(const codec::value &audio_codec) {
|
||||
codec_data.state = AudioCodec::State::INITIALIZED_FAIL;
|
||||
codec_data.converter = info->new_converter(error);
|
||||
if(!codec_data.converter) {
|
||||
log_warn(category::voice_connection, tr("Failed to initialized codec {} for client {}. Failed to initialize decoder: {}"), audio_codec, this->_client_id, error);
|
||||
log_warn(category::voice_connection, tr("Failed to initialized codec {} for client {}. Failed to initialize decoder: {}"), audio_codec, this->client_id_, error);
|
||||
return;
|
||||
}
|
||||
|
||||
codec_data.resampler = make_shared<audio::AudioResampler>(codec_data.converter->sample_rate(), this->output_source->sample_rate, this->output_source->channel_count);
|
||||
if(!codec_data.resampler->valid()) {
|
||||
log_warn(category::voice_connection, tr("Failed to initialized codec {} for client {}. Failed to initialize resampler"), audio_codec, this->_client_id);
|
||||
log_warn(category::voice_connection, tr("Failed to initialized codec {} for client {}. Failed to initialize resampler"), audio_codec, this->client_id_);
|
||||
return;
|
||||
}
|
||||
|
||||
codec_data.state = AudioCodec::State::INITIALIZED_SUCCESSFULLY;
|
||||
log_trace(category::voice_connection, tr("Successfully initialized codec {} for client {}."), audio_codec, this->_client_id);
|
||||
log_trace(category::voice_connection, tr("Successfully initialized codec {} for client {}."), audio_codec, this->client_id_);
|
||||
}
|
||||
|
||||
std::shared_ptr<audio::SampleBuffer> VoiceClient::decode_buffer(const codec::value &audio_codec, const pipes::buffer_view &buffer, bool fec) {
|
||||
@ -699,11 +706,11 @@ std::shared_ptr<audio::SampleBuffer> VoiceClient::decode_buffer(const codec::val
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(this->_volume != 1) {
|
||||
if(this->volume_ != 1) {
|
||||
auto buf = (float*) target_buffer;
|
||||
auto count = this->output_source->channel_count * resampled_samples;
|
||||
while(count-- > 0)
|
||||
*(buf++) *= this->_volume;
|
||||
*(buf++) *= this->volume_;
|
||||
}
|
||||
|
||||
auto audio_buffer = audio::SampleBuffer::allocate((uint8_t) this->output_source->channel_count, (uint16_t) resampled_samples);
|
||||
|
@ -69,24 +69,25 @@ namespace tc::connection {
|
||||
|
||||
void initialize();
|
||||
|
||||
inline uint16_t client_id() { return this->_client_id; }
|
||||
inline uint16_t client_id() { return this->client_id_; }
|
||||
|
||||
void initialize_js_object();
|
||||
void finalize_js_object();
|
||||
|
||||
v8::Local<v8::Object> js_handle() {
|
||||
assert(v8::Isolate::GetCurrent());
|
||||
return this->_js_handle.Get(Nan::GetCurrentContext()->GetIsolate());
|
||||
return this->js_handle_.Get(Nan::GetCurrentContext()->GetIsolate());
|
||||
}
|
||||
|
||||
inline std::shared_ptr<VoiceClient> ref() { return this->_ref.lock(); }
|
||||
inline std::shared_ptr<VoiceClient> ref() { return this->ref_.lock(); }
|
||||
|
||||
void process_packet(uint16_t packet_id, const pipes::buffer_view& /* buffer */, codec::value /* codec */, bool /* head */);
|
||||
void execute_tick();
|
||||
|
||||
inline float get_volume() { return this->_volume; }
|
||||
inline void set_volume(float value) { this->_volume = value; }
|
||||
inline float get_volume() { return this->volume_; }
|
||||
inline void set_volume(float value) { this->volume_ = value; }
|
||||
|
||||
inline state::value state() { return this->_state; }
|
||||
inline state::value state() { return this->state_; }
|
||||
|
||||
void cancel_replay();
|
||||
|
||||
@ -143,18 +144,18 @@ namespace tc::connection {
|
||||
/* might be null (if audio hasn't been initialized) */
|
||||
std::shared_ptr<audio::AudioOutputSource> output_source;
|
||||
|
||||
std::weak_ptr<VoiceClient> _ref;
|
||||
v8::Persistent<v8::Object> _js_handle;
|
||||
std::weak_ptr<VoiceClient> ref_;
|
||||
v8::Persistent<v8::Object> js_handle_;
|
||||
|
||||
uint16_t _client_id{0};
|
||||
float _volume = 1.f;
|
||||
uint16_t client_id_{0};
|
||||
float volume_{1.f};
|
||||
|
||||
std::chrono::system_clock::time_point _last_received_packet;
|
||||
state::value _state = state::stopped;
|
||||
state::value state_ = state::stopped;
|
||||
inline void set_state(state::value value) {
|
||||
if(value == this->_state)
|
||||
if(value == this->state_)
|
||||
return;
|
||||
this->_state = value;
|
||||
this->state_ = value;
|
||||
if(this->on_state_changed)
|
||||
this->on_state_changed();
|
||||
}
|
||||
|
@ -296,10 +296,20 @@ VoiceConnection::~VoiceConnection() {
|
||||
}
|
||||
|
||||
void VoiceConnection::reset() {
|
||||
lock_guard lock(this->_clients_lock);
|
||||
lock_guard lock{this->_clients_lock};
|
||||
this->_clients.clear();
|
||||
}
|
||||
|
||||
void VoiceConnection::execute_tick() {
|
||||
decltype(this->_clients) clients{};
|
||||
{
|
||||
std::lock_guard lg{this->_clients_lock};
|
||||
clients = this->_clients;
|
||||
}
|
||||
for(auto& client : clients)
|
||||
client->execute_tick();
|
||||
}
|
||||
|
||||
void VoiceConnection::initialize_js_object() {
|
||||
auto object_wrap = new VoiceConnectionWrap(this->ref());
|
||||
auto object = Nan::NewInstance(Nan::New(VoiceConnectionWrap::constructor()), 0, nullptr).ToLocalChecked();
|
||||
@ -313,7 +323,7 @@ void VoiceConnection::finalize_js_object() {
|
||||
}
|
||||
|
||||
std::shared_ptr<VoiceClient> VoiceConnection::find_client(uint16_t client_id) {
|
||||
lock_guard lock(this->_clients_lock);
|
||||
lock_guard lock{this->_clients_lock};
|
||||
for(const auto& client : this->_clients)
|
||||
if(client->client_id() == client_id)
|
||||
return client;
|
||||
@ -322,12 +332,12 @@ std::shared_ptr<VoiceClient> VoiceConnection::find_client(uint16_t client_id) {
|
||||
}
|
||||
|
||||
std::shared_ptr<VoiceClient> VoiceConnection::register_client(uint16_t client_id) {
|
||||
lock_guard lock(this->_clients_lock);
|
||||
lock_guard lock{this->_clients_lock};
|
||||
auto client = this->find_client(client_id);
|
||||
if(client) return client;
|
||||
|
||||
client = make_shared<VoiceClient>(this->ref(), client_id);
|
||||
client->_ref = client;
|
||||
client->ref_ = client;
|
||||
client->initialize();
|
||||
this->_clients.push_back(client);
|
||||
return client;
|
||||
|
@ -68,6 +68,7 @@ namespace tc {
|
||||
virtual ~VoiceConnection();
|
||||
|
||||
void reset();
|
||||
void execute_tick();
|
||||
|
||||
void initialize_js_object();
|
||||
void finalize_js_object();
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TeaClient",
|
||||
"version": "1.4.6-1",
|
||||
"version": "1.4.6-2",
|
||||
"description": "",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@ -13,7 +13,7 @@
|
||||
"start-n": "electron . -t --disable-hardware-acceleration --no-single-instance -u=https://clientapi.teaspeak.de/ -d",
|
||||
"start-nd": "electron . -t --disable-hardware-acceleration --no-single-instance -u=http://clientapi.teaspeak.dev/ -d",
|
||||
"start-01": "electron . --updater-channel=test -u=http://dev.clientapi.teaspeak.de/ -d --updater-ui-loader_type=0 --updater-local-version=1.0.1",
|
||||
"start-s": "electron . --disable-hardware-acceleration --debug --updater-ui-loader_type=2 --updater-ui-ignore-version -t -u http://localhost:8081/",
|
||||
"start-s": "electron . --disable-hardware-acceleration --gdb --debug --updater-ui-loader_type=2 --updater-ui-ignore-version -t -u http://localhost:8081/",
|
||||
"dtest": "electron . dtest",
|
||||
"compile-sass": "sass --update .:.",
|
||||
"compile-tsc": "tsc",
|
||||
|
Loading…
Reference in New Issue
Block a user