Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 89 additions & 58 deletions src/ScreenReaderDriverBOY.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,72 +11,103 @@

#include "ScreenReaderDriverBOY.h"

// Global variable to store the reason value
//Reason: Reason for callback, 1=speaking completed, 2=Interrupted by new speaking, 3=Interrupted by stopped call
static int g_speakCompleteReason = -1; // -1 indicates no speech activity
// Global variable to store the reason value.
// Reason: 0=no speech activity, -1=speaking, 1=speaking completed,
// 2=interrupted by new speaking, 3=interrupted by stopped call.
static int g_speakCompleteReason = 0;

// Callback function to be called when speaking is complete
void __stdcall SpeakCompleteCallback(int reason) {
g_speakCompleteReason = reason;
}

ScreenReaderDriverBOY::ScreenReaderDriverBOY() :
ScreenReaderDriver(L"BoyPCReader", true, false),
#ifdef _WIN64
controller(LoadLibrary(L"BoyCtrl-x64.dll")),
#else
controller(LoadLibrary(L"BoyCtrl.dll")),
#endif
BoySpeak(NULL),
BoyStopSpeak(NULL),
BoyInit(NULL),
BoyUninit(NULL),
BoyIsRunning(NULL)
{
if (controller) {
BoyInit = (BoyCtrlInitialize)GetProcAddress(controller, "BoyCtrlInitialize");
BoyUninit = (BoyCtrlUninitialize)GetProcAddress(controller, "BoyCtrlUninitialize");
BoyIsRunning = (BoyCtrlIsReaderRunning)GetProcAddress(controller, "BoyCtrlIsReaderRunning");
BoySpeak = (BoyCtrlSpeak)GetProcAddress(controller, "BoyCtrlSpeak");
BoyStopSpeak = (BoyCtrlStopSpeaking)GetProcAddress(controller, "BoyCtrlStopSpeaking");
BoyInit(NULL);
}
}

ScreenReaderDriverBOY::~ScreenReaderDriverBOY() {
if (controller) {
BoyUninit();
FreeLibrary(controller);
}
}

bool ScreenReaderDriverBOY::Speak(const wchar_t *str, bool interrupt) {
g_speakCompleteReason = -1; // Reset the reason to indicate speaking has started
if (BoySpeak) return (BoySpeak(str, true, !interrupt, true, SpeakCompleteCallback) == 0);
return false;
}
ScreenReaderDriverBOY::ScreenReaderDriverBOY() :
ScreenReaderDriver(L"BoyPCReader", true, false),
#ifdef _WIN64
controller(LoadLibrary(L"byctrl-x64.dll")),
#else
controller(LoadLibrary(L"byctrl.dll")),
#endif
initialized(false),
BoySpeak(NULL),
BoyStopSpeak(NULL),
BoyInit(NULL),
BoyUninit(NULL),
BoyIsRunning(NULL)
{
if (!controller) return;

BoyInit = (BoyCtrlInitialize)GetProcAddress(controller, "BoyCtrlInitialize");
BoyUninit = (BoyCtrlUninitialize)GetProcAddress(controller, "BoyCtrlUninitialize");
BoyIsRunning = (BoyCtrlIsReaderRunning)GetProcAddress(controller, "BoyCtrlIsReaderRunning");
BoySpeak = (BoyCtrlSpeak)GetProcAddress(controller, "BoyCtrlSpeak");
BoyStopSpeak = (BoyCtrlStopSpeaking)GetProcAddress(controller, "BoyCtrlStopSpeaking");

if (!BoyInit || !BoyUninit || !BoyIsRunning || !BoySpeak || !BoyStopSpeak) {
FreeLibrary(controller);
controller = NULL;
BoyInit = NULL;
BoyUninit = NULL;
BoyIsRunning = NULL;
BoySpeak = NULL;
BoyStopSpeak = NULL;
return;
}

if (BoyInit(NULL) != 0) {
FreeLibrary(controller);
controller = NULL;
BoyInit = NULL;
BoyUninit = NULL;
BoyIsRunning = NULL;
BoySpeak = NULL;
BoyStopSpeak = NULL;
return;
}

initialized = true;
}

ScreenReaderDriverBOY::~ScreenReaderDriverBOY() {
if (initialized && BoyUninit) {
BoyUninit();
initialized = false;
}
if (controller) {
FreeLibrary(controller);
controller = NULL;
}
}

bool ScreenReaderDriverBOY::Speak(const wchar_t *str, bool interrupt) {
if (!initialized || !BoySpeak) return false;
g_speakCompleteReason = -1;
if (BoySpeak(str, !interrupt, SpeakCompleteCallback) == 0) return true;
g_speakCompleteReason = 0;
return false;
}

bool ScreenReaderDriverBOY::Braille(const wchar_t *str) {
return false;
}

bool ScreenReaderDriverBOY::Silence() {
if (BoyStopSpeak) {
BoyStopSpeak(true);
g_speakCompleteReason = 3;
return true;
}
return false;
}
bool ScreenReaderDriverBOY::Braille(const wchar_t *str) {
(void)str;
return false;
}

bool ScreenReaderDriverBOY::IsSpeaking() {
return (g_speakCompleteReason == -1);
}

bool ScreenReaderDriverBOY::IsActive() {
if (BoyIsRunning) return BoyIsRunning();
return false;
}
bool ScreenReaderDriverBOY::Silence() {
if (initialized && BoyStopSpeak && BoyStopSpeak() == 0) {
g_speakCompleteReason = 3;
return true;
}
return false;
}

bool ScreenReaderDriverBOY::IsSpeaking() {
return (initialized && g_speakCompleteReason == -1);
}

bool ScreenReaderDriverBOY::IsActive() {
if (initialized && BoyIsRunning) return BoyIsRunning();
return false;
}

bool ScreenReaderDriverBOY::Output(const wchar_t *str, bool interrupt) {
const bool speak = Speak(str, interrupt);
Expand Down
26 changes: 13 additions & 13 deletions src/ScreenReaderDriverBOY.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ class ScreenReaderDriverBOY : public ScreenReaderDriver {
bool IsActive();
bool Output(const wchar_t *str, bool interrupt);

private:
typedef int (__stdcall *BoyCtrlInitialize)(const wchar_t* pathName);
typedef void (__stdcall *BoyCtrlUninitialize)();
typedef bool (__stdcall *BoyCtrlIsReaderRunning)();
typedef int (__stdcall *BoyCtrlSpeak)(const wchar_t* text, bool withSlave, bool append, bool allowBreak, BoyCtrlSpeakCompleteFunc onCompletion);
typedef int (__stdcall *BoyCtrlStopSpeaking)(bool withSlave);
private:
HINSTANCE controller;
BoyCtrlInitialize BoyInit;
BoyCtrlUninitialize BoyUninit;
BoyCtrlIsReaderRunning BoyIsRunning;
private:
typedef int (__stdcall *BoyCtrlInitialize)(const wchar_t *logPath);
typedef void (__stdcall *BoyCtrlUninitialize)();
typedef bool (__stdcall *BoyCtrlIsReaderRunning)();
typedef int (__stdcall *BoyCtrlSpeak)(const wchar_t *text, bool append, BoyCtrlSpeakCompleteFunc onCompletion);
typedef int (__stdcall *BoyCtrlStopSpeaking)();

private:
HINSTANCE controller;
bool initialized;
BoyCtrlInitialize BoyInit;
BoyCtrlUninitialize BoyUninit;
BoyCtrlIsReaderRunning BoyIsRunning;
BoyCtrlSpeak BoySpeak;
BoyCtrlStopSpeaking BoyStopSpeak;
};
Expand Down