Make the TriggerVibrationvibration behave closer to real steam.

This commit is contained in:
Mr_Goldberg 2021-09-14 16:11:17 -04:00
parent b3a5102a3c
commit a24a9c266f
No known key found for this signature in database
GPG key ID: 8597D87419DEF278
3 changed files with 108 additions and 4 deletions

View file

@ -262,6 +262,7 @@ STEAMAPI_API void S_CALLTYPE SteamAPI_Shutdown()
PRINT_DEBUG("SteamAPI_Shutdown\n"); PRINT_DEBUG("SteamAPI_Shutdown\n");
get_steam_client()->clientShutdown(); get_steam_client()->clientShutdown();
get_steam_client()->BReleaseSteamPipe(user_steam_pipe); get_steam_client()->BReleaseSteamPipe(user_steam_pipe);
get_steam_client()->BShutdownIfAllPipesClosed();
user_steam_pipe = 0; user_steam_pipe = 0;
--global_counter; --global_counter;
old_user_instance = NULL; old_user_instance = NULL;
@ -652,6 +653,7 @@ STEAMAPI_API void SteamGameServer_Shutdown()
PRINT_DEBUG("SteamGameServer_Shutdown\n"); PRINT_DEBUG("SteamGameServer_Shutdown\n");
get_steam_client()->serverShutdown(); get_steam_client()->serverShutdown();
get_steam_client()->BReleaseSteamPipe(server_steam_pipe); get_steam_client()->BReleaseSteamPipe(server_steam_pipe);
get_steam_client()->BShutdownIfAllPipesClosed();
server_steam_pipe = 0; server_steam_pipe = 0;
--global_counter; --global_counter;
g_pSteamClientGameServer = NULL; //TODO: check if this actually gets nulled when SteamGameServer_Shutdown is called g_pSteamClientGameServer = NULL; //TODO: check if this actually gets nulled when SteamGameServer_Shutdown is called

View file

@ -794,9 +794,14 @@ bool Steam_Client::BShutdownIfAllPipesClosed()
{ {
PRINT_DEBUG("BShutdownIfAllPipesClosed\n"); PRINT_DEBUG("BShutdownIfAllPipesClosed\n");
if (!steam_pipes.size()) { if (!steam_pipes.size()) {
if (background_keepalive.joinable()) { bool joinable = background_keepalive.joinable();
if (joinable) {
kill_background_thread = true; kill_background_thread = true;
kill_background_thread_cv.notify_one(); kill_background_thread_cv.notify_one();
}
steam_controller->Shutdown();
if (joinable) {
background_keepalive.join(); background_keepalive.join();
} }

View file

@ -63,6 +63,19 @@ struct Controller_Action {
} }
}; };
struct Rumble_Thread_Data {
std::condition_variable rumble_thread_cv;
std::atomic_bool kill_rumble_thread;
std::mutex rumble_mutex;
struct Rumble_Data {
unsigned short left, right, last_left, last_right;
unsigned int rumble_length_ms;
bool new_data;
} data[GAMEPAD_COUNT];
};
enum EXTRA_GAMEPAD_BUTTONS { enum EXTRA_GAMEPAD_BUTTONS {
BUTTON_LTRIGGER = BUTTON_COUNT + 1, BUTTON_LTRIGGER = BUTTON_COUNT + 1,
BUTTON_RTRIGGER = BUTTON_COUNT + 2, BUTTON_RTRIGGER = BUTTON_COUNT + 2,
@ -146,6 +159,9 @@ public ISteamInput
std::map<EInputActionOrigin, std::string> steaminput_glyphs; std::map<EInputActionOrigin, std::string> steaminput_glyphs;
std::map<EControllerActionOrigin, std::string> steamcontroller_glyphs; std::map<EControllerActionOrigin, std::string> steamcontroller_glyphs;
std::thread background_rumble_thread;
Rumble_Thread_Data *rumble_thread_data;
bool disabled; bool disabled;
bool initialized; bool initialized;
@ -210,6 +226,66 @@ public ISteamInput
public: public:
static void background_rumble(Rumble_Thread_Data *data)
{
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
bool rumbled = false;
while (true) {
bool new_data = false;
if (rumbled) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
data->rumble_mutex.lock();
for (int i = 0; i < GAMEPAD_COUNT; ++i) {
if (data->data[i].new_data) {
new_data = true;
break;
}
}
data->rumble_mutex.unlock();
if (data->kill_rumble_thread) {
return;
}
}
bool x = new_data || data->rumble_thread_cv.wait_for(lck, std::chrono::milliseconds(100)) != std::cv_status::timeout;
if (data->kill_rumble_thread) {
return;
}
rumbled = false;
while (true) {
unsigned short left, right;
unsigned int rumble_length_ms;
int gamepad = -1;
data->rumble_mutex.lock();
for (int i = 0; i < GAMEPAD_COUNT; ++i) {
if (data->data[i].new_data) {
left = data->data[i].left;
right = data->data[i].right;
rumble_length_ms = data->data[i].rumble_length_ms;
data->data[i].new_data = false;
if (data->data[i].last_left != left || data->data[i].last_right != right) {
gamepad = i;
data->data[i].last_left = left;
data->data[i].last_right = right;
break;
}
}
}
data->rumble_mutex.unlock();
if (gamepad == -1) {
break;
}
GamepadSetRumble((GAMEPAD_DEVICE)gamepad, ((double)left) / 65535.0, ((double)right) / 65535.0, rumble_length_ms);
rumbled = true;
}
}
}
static void steam_run_every_runcb(void *object) static void steam_run_every_runcb(void *object)
{ {
PRINT_DEBUG("steam_controller_run_every_runcb\n"); PRINT_DEBUG("steam_controller_run_every_runcb\n");
@ -235,6 +311,7 @@ Steam_Controller(class Settings *settings, class SteamCallResults *callback_resu
~Steam_Controller() ~Steam_Controller()
{ {
//TODO rm network callbacks //TODO rm network callbacks
//TODO rumble thread
this->run_every_runcb->remove(&Steam_Controller::steam_run_every_runcb, this); this->run_every_runcb->remove(&Steam_Controller::steam_run_every_runcb, this);
} }
@ -243,7 +320,7 @@ bool Init()
{ {
PRINT_DEBUG("Steam_Controller::Init()\n"); PRINT_DEBUG("Steam_Controller::Init()\n");
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (disabled) { if (disabled || initialized) {
return true; return true;
} }
@ -261,6 +338,9 @@ bool Init()
controllers.insert(std::pair<ControllerHandle_t, struct Controller_Action>(i, cont_action)); controllers.insert(std::pair<ControllerHandle_t, struct Controller_Action>(i, cont_action));
} }
rumble_thread_data = new Rumble_Thread_Data();
background_rumble_thread = std::thread(background_rumble, rumble_thread_data);
initialized = true; initialized = true;
return true; return true;
} }
@ -275,11 +355,17 @@ bool Shutdown()
{ {
PRINT_DEBUG("Steam_Controller::Shutdown()\n"); PRINT_DEBUG("Steam_Controller::Shutdown()\n");
std::lock_guard<std::recursive_mutex> lock(global_mutex); std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (disabled) { if (disabled || !initialized) {
return true; return true;
} }
controllers = std::map<ControllerHandle_t, struct Controller_Action>();
rumble_thread_data->kill_rumble_thread = true;
rumble_thread_data->rumble_thread_cv.notify_one();
background_rumble_thread.join();
delete rumble_thread_data;
GamepadShutdown(); GamepadShutdown();
initialized = false;
return true; return true;
} }
@ -350,6 +436,7 @@ ControllerActionSetHandle_t GetActionSetHandle( const char *pszActionSetName )
auto set_handle = action_handles.find(upper_action_name); auto set_handle = action_handles.find(upper_action_name);
if (set_handle == action_handles.end()) return 0; if (set_handle == action_handles.end()) return 0;
PRINT_DEBUG("Steam_Controller::GetActionSetHandle %s ret %llu\n", pszActionSetName, set_handle->second);
return set_handle->second; return set_handle->second;
} }
@ -417,6 +504,7 @@ ControllerDigitalActionHandle_t GetDigitalActionHandle( const char *pszActionNam
auto handle = digital_action_handles.find(upper_action_name); auto handle = digital_action_handles.find(upper_action_name);
if (handle == digital_action_handles.end()) return 0; if (handle == digital_action_handles.end()) return 0;
PRINT_DEBUG("Steam_Controller::GetDigitalActionHandle %s ret %llu\n", pszActionName, handle->second);
return handle->second; return handle->second;
} }
@ -762,7 +850,16 @@ void TriggerVibration( ControllerHandle_t controllerHandle, unsigned short usLef
//FIXME: shadow of the tomb raider on linux doesn't seem to turn off the rumble so I made it expire after 100ms. Need to check if this is how linux steam actually behaves. //FIXME: shadow of the tomb raider on linux doesn't seem to turn off the rumble so I made it expire after 100ms. Need to check if this is how linux steam actually behaves.
rumble_length_ms = 100; rumble_length_ms = 100;
#endif #endif
GamepadSetRumble((GAMEPAD_DEVICE)(controllerHandle - 1), ((double)usLeftSpeed) / 65535.0, ((double)usRightSpeed) / 65535.0, rumble_length_ms);
unsigned gamepad_device = (controllerHandle - 1);
if (gamepad_device > GAMEPAD_COUNT) return;
rumble_thread_data->rumble_mutex.lock();
rumble_thread_data->data[gamepad_device].new_data = true;
rumble_thread_data->data[gamepad_device].left = usLeftSpeed;
rumble_thread_data->data[gamepad_device].right = usRightSpeed;
rumble_thread_data->data[gamepad_device].rumble_length_ms = rumble_length_ms;
rumble_thread_data->rumble_mutex.unlock();
rumble_thread_data->rumble_thread_cv.notify_one();
} }