Fixed the native audio playback
This commit is contained in:
		
							parent
							
								
									fe947ea83b
								
							
						
					
					
						commit
						0a6c68f940
					
				@ -10,6 +10,7 @@ import {processArguments} from "../../shared/process-arguments";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import "./ExternalModal";
 | 
					import "./ExternalModal";
 | 
				
			||||||
import {showUpdateWindow} from "../windows/client-updater/controller/ClientUpdate";
 | 
					import {showUpdateWindow} from "../windows/client-updater/controller/ClientUpdate";
 | 
				
			||||||
 | 
					import {getUiFilePath} from "../ui-loader/Loader";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ipcMain.on('basic-action', (event, action, ...args: any[]) => {
 | 
					ipcMain.on('basic-action', (event, action, ...args: any[]) => {
 | 
				
			||||||
    const window = BrowserWindow.fromWebContents(event.sender);
 | 
					    const window = BrowserWindow.fromWebContents(event.sender);
 | 
				
			||||||
@ -28,3 +29,5 @@ ipcMain.on('basic-action', (event, action, ...args: any[]) => {
 | 
				
			|||||||
        window.close();
 | 
					        window.close();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ipcMain.handle("tc-get-ui-path", () => getUiFilePath());
 | 
				
			||||||
@ -125,8 +125,14 @@ async function unpackLocalUiPack(version: CachedUIPack) : Promise<string> {
 | 
				
			|||||||
    return targetDirectory;
 | 
					    return targetDirectory;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let uiFilePath: string;
 | 
				
			||||||
 | 
					export function getUiFilePath() : string | undefined {
 | 
				
			||||||
 | 
					    return uiFilePath;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function initializeFileSystemProtocol(directory: string) {
 | 
					function initializeFileSystemProtocol(directory: string) {
 | 
				
			||||||
    directory = path.normalize(directory);
 | 
					    directory = path.normalize(directory);
 | 
				
			||||||
 | 
					    uiFilePath = directory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protocol.registerFileProtocol(kUiPackProtocol, (request, callback) => {
 | 
					    protocol.registerFileProtocol(kUiPackProtocol, (request, callback) => {
 | 
				
			||||||
        let targetPath;
 | 
					        let targetPath;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,27 +1,52 @@
 | 
				
			|||||||
import {audio as naudio} from "tc-native/connection";
 | 
					import {audio as naudio} from "tc-native/connection";
 | 
				
			||||||
import {SoundBackend, SoundFile} from "tc-shared/audio/Sounds";
 | 
					import {SoundBackend, SoundFile} from "tc-shared/audio/Sounds";
 | 
				
			||||||
import * as paths from "path";
 | 
					import * as paths from "path";
 | 
				
			||||||
 | 
					import * as loader from "tc-loader";
 | 
				
			||||||
 | 
					import {Stage} from "tc-loader";
 | 
				
			||||||
 | 
					import {ipcRenderer} from "electron";
 | 
				
			||||||
 | 
					import {LogCategory, logDebug, logInfo} from "tc-shared/log";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let uiFilePath;
 | 
				
			||||||
export class NativeSoundBackend implements SoundBackend {
 | 
					export class NativeSoundBackend implements SoundBackend {
 | 
				
			||||||
    playSound(sound: SoundFile): Promise<void> {
 | 
					    playSound(sound: SoundFile): Promise<void> {
 | 
				
			||||||
        return new Promise((resolve, reject) => {
 | 
					        return new Promise((resolve, reject) => {
 | 
				
			||||||
            let pathname = paths.dirname(decodeURIComponent(location.pathname));
 | 
					            if(!uiFilePath) {
 | 
				
			||||||
            if(pathname[0] === '/' && pathname[2] === ':') //e.g.: /C:/test...
 | 
					                reject("Mussing UI file path");
 | 
				
			||||||
                pathname = pathname.substr(1);
 | 
					                return;
 | 
				
			||||||
            const path = paths.join(pathname, sound.path);
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            console.log("replaying %s (volume: %f)", sound.path, sound.volume);
 | 
					            const path = paths.join(uiFilePath, sound.path);
 | 
				
			||||||
 | 
					            console.log("replaying %s (volume: %f) from %s", sound.path, sound.volume, path);
 | 
				
			||||||
            naudio.sounds.playback_sound({
 | 
					            naudio.sounds.playback_sound({
 | 
				
			||||||
                callback: (result, message) => {
 | 
					                callback: (result, message) => {
 | 
				
			||||||
                    if(result == naudio.sounds.PlaybackResult.SUCCEEDED)
 | 
					                    if(result == naudio.sounds.PlaybackResult.SUCCEEDED) {
 | 
				
			||||||
                        resolve();
 | 
					                        resolve();
 | 
				
			||||||
                    else
 | 
					                    } else {
 | 
				
			||||||
                        reject(naudio.sounds.PlaybackResult[result].toLowerCase() + ": " + message);
 | 
					                        reject(naudio.sounds.PlaybackResult[result].toLowerCase() + ": " + message);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                file: path,
 | 
					                file: path,
 | 
				
			||||||
                volume: typeof sound.volume === "number" ? sound.volume : 1
 | 
					                volume: typeof sound.volume === "number" ? sound.volume : 1
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//tc-get-ui-path
 | 
				
			||||||
 | 
					loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
 | 
				
			||||||
 | 
					    name: "sound initialize",
 | 
				
			||||||
 | 
					    priority: 50,
 | 
				
			||||||
 | 
					    function: async () => {
 | 
				
			||||||
 | 
					        uiFilePath = await ipcRenderer.invoke("tc-get-ui-path");
 | 
				
			||||||
 | 
					        if(!uiFilePath) {
 | 
				
			||||||
 | 
					            logInfo(LogCategory.AUDIO, tr("Missing UI path. App sounds will not work."));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if(uiFilePath[0] === '/' && uiFilePath[2] === ':') {
 | 
				
			||||||
 | 
					                //e.g.: /C:/test...
 | 
				
			||||||
 | 
					                uiFilePath = uiFilePath.substr(1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            logDebug(LogCategory.AUDIO, tr("Received UI path: %s"), uiFilePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@ -270,7 +270,7 @@ ssize_t AudioOutputSource::enqueue_samples_no_interleave(const void *source_buff
 | 
				
			|||||||
bool AudioOutputSource::set_max_buffered_samples(size_t samples) {
 | 
					bool AudioOutputSource::set_max_buffered_samples(size_t samples) {
 | 
				
			||||||
    samples = std::max(samples, (size_t) this->fadein_frame_samples_);
 | 
					    samples = std::max(samples, (size_t) this->fadein_frame_samples_);
 | 
				
			||||||
    if(samples > this->max_supported_buffering()) {
 | 
					    if(samples > this->max_supported_buffering()) {
 | 
				
			||||||
        return false;
 | 
					        samples = this->max_supported_buffering();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::lock_guard buffer_lock{this->buffer_mutex};
 | 
					    std::lock_guard buffer_lock{this->buffer_mutex};
 | 
				
			||||||
 | 
				
			|||||||
@ -87,8 +87,9 @@ namespace tc::audio::sounds {
 | 
				
			|||||||
                    this->file_handle = std::make_unique<file::WAVReader>(this->settings_.file);
 | 
					                    this->file_handle = std::make_unique<file::WAVReader>(this->settings_.file);
 | 
				
			||||||
                    std::string error{};
 | 
					                    std::string error{};
 | 
				
			||||||
                    if(auto err{this->file_handle->open_file(error)}; err != file::OPEN_RESULT_SUCCESS) {
 | 
					                    if(auto err{this->file_handle->open_file(error)}; err != file::OPEN_RESULT_SUCCESS) {
 | 
				
			||||||
                        if(auto callback{this->settings_.callback}; callback)
 | 
					                        if(auto callback{this->settings_.callback}; callback) {
 | 
				
			||||||
                            callback(PlaybackResult::FILE_OPEN_ERROR, error);
 | 
					                            callback(PlaybackResult::FILE_OPEN_ERROR, error);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        this->finalize(false);
 | 
					                        this->finalize(false);
 | 
				
			||||||
                        return;
 | 
					                        return;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -175,21 +176,27 @@ namespace tc::audio::sounds {
 | 
				
			|||||||
                auto weak_this = this->weak_from_this();
 | 
					                auto weak_this = this->weak_from_this();
 | 
				
			||||||
                this->output_source->on_underflow = [weak_this](size_t sample_count){
 | 
					                this->output_source->on_underflow = [weak_this](size_t sample_count){
 | 
				
			||||||
                    auto self = weak_this.lock();
 | 
					                    auto self = weak_this.lock();
 | 
				
			||||||
                    if(!self) return false;
 | 
					                    if(!self) {
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if(self->state_ == PLAYER_STATE_PLAYING)
 | 
					                    if(self->state_ == PLAYER_STATE_PLAYING) {
 | 
				
			||||||
                        log_warn(category::audio, tr("Having an audio underflow while playing a sound."));
 | 
					                        log_warn(category::audio, tr("Having an audio underflow while playing a sound."));
 | 
				
			||||||
                    else if(self->state_ == PLAYER_STATE_AWAIT_FINISH)
 | 
					                    } else if(self->state_ == PLAYER_STATE_AWAIT_FINISH) {
 | 
				
			||||||
                        self->state_ = PLAYER_STATE_FINISHED;
 | 
					                        self->state_ = PLAYER_STATE_FINISHED;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    audio::decode_event_loop->schedule(self);
 | 
					                    audio::decode_event_loop->schedule(self);
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                this->output_source->on_read = [weak_this] {
 | 
					                this->output_source->on_read = [weak_this] {
 | 
				
			||||||
                    auto self = weak_this.lock();
 | 
					                    auto self = weak_this.lock();
 | 
				
			||||||
                    if(!self) return;
 | 
					                    if(!self) {
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if(self->could_enqueue_next_buffer() && self->state_ == PLAYER_STATE_PLAYING)
 | 
					                    if(self->could_enqueue_next_buffer() && self->state_ == PLAYER_STATE_PLAYING) {
 | 
				
			||||||
                        audio::decode_event_loop->schedule(self);
 | 
					                        audio::decode_event_loop->schedule(self);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this->output_source->on_overflow = [weak_this](size_t count) {
 | 
					                this->output_source->on_overflow = [weak_this](size_t count) {
 | 
				
			||||||
@ -205,7 +212,9 @@ namespace tc::audio::sounds {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            [[nodiscard]] inline bool could_enqueue_next_buffer() const {
 | 
					            [[nodiscard]] inline bool could_enqueue_next_buffer() const {
 | 
				
			||||||
                if(!this->output_source) return false;
 | 
					                if(!this->output_source) {
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                const auto current_size = this->output_source->currently_buffered_samples();
 | 
					                const auto current_size = this->output_source->currently_buffered_samples();
 | 
				
			||||||
                const auto max_size = this->output_source->max_buffered_samples();
 | 
					                const auto max_size = this->output_source->max_buffered_samples();
 | 
				
			||||||
@ -233,8 +242,9 @@ namespace tc::audio::sounds {
 | 
				
			|||||||
        auto player = std::make_shared<FilePlayer>(settings);
 | 
					        auto player = std::make_shared<FilePlayer>(settings);
 | 
				
			||||||
        file_players.push_back(player);
 | 
					        file_players.push_back(player);
 | 
				
			||||||
        if(!player->play()) {
 | 
					        if(!player->play()) {
 | 
				
			||||||
            if(auto callback{settings.callback}; callback)
 | 
					            if(auto callback{settings.callback}; callback) {
 | 
				
			||||||
                callback(PlaybackResult::PLAYBACK_ERROR, "failed to start playback.");
 | 
					                callback(PlaybackResult::PLAYBACK_ERROR, "failed to start playback.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        fplock.unlock();
 | 
					        fplock.unlock();
 | 
				
			||||||
@ -244,7 +254,9 @@ namespace tc::audio::sounds {
 | 
				
			|||||||
    void cancel_playback(const sound_playback_id& id) {
 | 
					    void cancel_playback(const sound_playback_id& id) {
 | 
				
			||||||
        std::unique_lock fplock{file_player_mutex};
 | 
					        std::unique_lock fplock{file_player_mutex};
 | 
				
			||||||
        auto player_it = std::find_if(file_players.begin(), file_players.end(), [&](const auto& player) { return (sound_playback_id) &*player == id; });
 | 
					        auto player_it = std::find_if(file_players.begin(), file_players.end(), [&](const auto& player) { return (sound_playback_id) &*player == id; });
 | 
				
			||||||
        if(player_it == file_players.end()) return;
 | 
					        if(player_it == file_players.end()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto player = *player_it;
 | 
					        auto player = *player_it;
 | 
				
			||||||
        file_players.erase(player_it);
 | 
					        file_players.erase(player_it);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user