From 667711246ed0abb5d24dfc724575520cdd38d502 Mon Sep 17 00:00:00 2001 From: Vasily Date: Mon, 21 Jan 2019 21:11:28 +0100 Subject: [PATCH] Add media key bindings, update docs All bindings are disabled by default. This is to prevent confusing behaviour from users who do not know about the new bindings. Forcing users to manually set up their bindings will also enable them to play around with the SteamVR bindings interface, which allows for much more versatile binding options that our current offerings. All actions are curently in main action set. If the selection of bindings was greatly expanded it could be beneficial to encapsulate the options more. The current code is more intended as a proof of concept until our full binding needs have been uncovered. The processInputBindings function should probably also be split into several functions of related bindings, as the amount of bindings grows. --- Readme.md | 17 +++++--- src/ivrinput/ivrinput.cpp | 40 ++++++++++++++++++- src/ivrinput/ivrinput.h | 13 +++++- src/overlaycontroller.cpp | 32 +++++++++++++-- src/overlaycontroller.h | 4 +- src/package_files/action_manifest.json | 24 +++++++++-- .../vive_defaults.json | 34 ++-------------- 7 files changed, 117 insertions(+), 47 deletions(-) diff --git a/Readme.md b/Readme.md index 008bd58..a5b2af1 100644 --- a/Readme.md +++ b/Readme.md @@ -83,20 +83,25 @@ To upgrade an existing installation first stop SteamVR and delete the old applic ## Bindings -Advanced Settings supports the OpenVR IVRInput API. In order to make the bindings interface visible, run the `bindingsinterface.bat` file from the install directory. When SteamVR starts, click the menu -> Settings -> Controller Binding. +Advanced Settings supports the OpenVR IVRInput API. In order to make the bindings interface visible, run the `bindingsinterface.bat` file from the install directory. After you're done configuring your bindings, close SteamVR and start it up again. You are now using your new bindings. -If you just run the application normally it will not show up in the bindings interface, this is an OpenVR bug. +Alternatively, you can change the `matzman666.AdvancedSettings.vrappconfig` in `C:\Program Files (x86)\Steam\config\vrappconfig` to have a `last_launch_time` close to the current date (in [Unix time](https://en.wikipedia.org/wiki/Unix_time)). If in doubt, try using the value from [this](https://time.is/Unix_time_now) site. Running the application normally will now make it show up in the bindings interface. -After you're done configuring your bindings, close SteamVR and start it up again. You are now using your new bindings. +The above two solutions are workarounds to a bug in the OpenVR API. + +After doing one of the above workarounds, when SteamVR starts click the menu -> Settings -> Controller Binding. By default no buttons are bound. -The following actions exist: +The following actions currently exist: | Action | Type | Explanation | | ------------- | ------------- | ------------ | -| PlayNextSong | Binary/Button | The same as using the media keys. Plays the next song. | -| TODO | TODO | TODO | +| NextSong | Binary/Button | The same as using the media keys. Tells a media player to play the next song.| +| PreviousSong | Binary/Button | The same as using the media keys. Tells a media player to play the previous song. | +| pausePlaySong | Binary/Button | The same as using the media keys. Tells the media player to press play/pause. | +| stopSong | Binary/Button | The same as using the media keys. Tells the media player to stop playback. | + ## Command Line Arguments diff --git a/src/ivrinput/ivrinput.cpp b/src/ivrinput/ivrinput.cpp index fa5aa9a..5e0e792 100644 --- a/src/ivrinput/ivrinput.cpp +++ b/src/ivrinput/ivrinput.cpp @@ -124,7 +124,12 @@ mystically not working. */ SteamIVRInput::SteamIVRInput() : m_manifest(), m_mainSet( input_strings::k_setMain ), - m_nextTrack( input_strings::k_actionNextTrack, ActionType::Digital ) + m_nextTrack( input_strings::k_actionNextTrack, ActionType::Digital ), + m_previousTrack( input_strings::k_actionPreviousTrack, + ActionType::Digital ), + m_pausePlayTrack( input_strings::k_actionPausePlayTrack, + ActionType::Digital ), + m_stopTrack( input_strings::k_actionStopTrack, ActionType::Digital ) { m_activeActionSet.ulActionSet = m_mainSet.handle(); m_activeActionSet.ulRestrictedToDevice = vr::k_ulInvalidInputValueHandle; @@ -141,6 +146,39 @@ bool SteamIVRInput::nextSong() return isDigitalActionActivatedOnce( m_nextTrack ); } +/*! +Returns true if the previous media track should be played. + +Will only return true the first time that the button is pressed. Holding the +button down will result in false until it has been released and pushed again. +*/ +bool SteamIVRInput::previousSong() +{ + return isDigitalActionActivatedOnce( m_previousTrack ); +} + +/*! +Returns true if media playback should be paused/played. + +Will only return true the first time that the button is pressed. Holding the +button down will result in false until it has been released and pushed again. +*/ +bool SteamIVRInput::pausePlaySong() +{ + return isDigitalActionActivatedOnce( m_pausePlayTrack ); +} + +/*! +Returns true if media playback should be stopped. + +Will only return true the first time that the button is pressed. Holding the +button down will result in false until it has been released and pushed again. +*/ +bool SteamIVRInput::stopSong() +{ + return isDigitalActionActivatedOnce( m_stopTrack ); +} + /*! Updates the active action set(s). Should be called every frame, or however often you want the input system to diff --git a/src/ivrinput/ivrinput.h b/src/ivrinput/ivrinput.h index 7bd2736..975a447 100644 --- a/src/ivrinput/ivrinput.h +++ b/src/ivrinput/ivrinput.h @@ -37,6 +37,9 @@ public: void UpdateStates(); bool nextSong(); + bool previousSong(); + bool pausePlaySong(); + bool stopSong(); // Destructor. There are no terminating calls for the IVRInput API, so it // is left blank. @@ -61,7 +64,11 @@ private: ActionSet m_mainSet; vr::VRActiveActionSet_t m_activeActionSet = {}; + // Music player bindings Action m_nextTrack; + Action m_previousTrack; + Action m_pausePlayTrack; + Action m_stopTrack; }; /*! @@ -71,7 +78,11 @@ should be used to refer to all action manifest strings. */ namespace input_strings { - constexpr auto k_actionNextTrack = "/actions/main/in/PlayNextTrack"; + constexpr auto k_actionNextTrack = "/actions/main/in/NextTrack"; + constexpr auto k_actionPreviousTrack = "/actions/main/in/PreviousTrack"; + constexpr auto k_actionPausePlayTrack = "/actions/main/in/PausePlayTrack"; + constexpr auto k_actionStopTrack = "/actions/main/in/StopTrack"; + constexpr auto k_setMain = "/actions/main"; } // namespace input_strings diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index 314b068..59f2dd3 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -471,6 +471,33 @@ QPoint OverlayController::getMousePositionForEvent( vr::VREvent_Mouse_t mouse ) return QPoint( mouse.x, y ); } +/*! +Checks if an action has been activated and dispatches the related action if it +has been. + +This function should probably be split into several functions that are specific +to a binding type as the amount of actions grows. +*/ +void OverlayController::processInputBindings() +{ + if ( m_actions.nextSong() ) + { + m_utilitiesTabController.sendMediaNextSong(); + } + if ( m_actions.previousSong() ) + { + m_utilitiesTabController.sendMediaPreviousSong(); + } + if ( m_actions.pausePlaySong() ) + { + m_utilitiesTabController.sendMediaPausePlay(); + } + if ( m_actions.stopSong() ) + { + m_utilitiesTabController.sendMediaStopSong(); + } +} + void OverlayController::OnTimeoutPumpEvents() { if ( !vr::VRSystem() ) @@ -478,10 +505,7 @@ void OverlayController::OnTimeoutPumpEvents() m_actions.UpdateStates(); - if ( m_actions.nextSong() ) - { - LOG( INFO ) << "NEXT SONG SET!"; - } + processInputBindings(); vr::VREvent_t vrEvent; bool chaperoneDataAlreadyUpdated = false; diff --git a/src/overlaycontroller.h b/src/overlaycontroller.h index 7f34462..06dc94b 100644 --- a/src/overlaycontroller.h +++ b/src/overlaycontroller.h @@ -90,9 +90,10 @@ private: // the class. openvr_init::OpenVR_Init m_openVrInit; + input::SteamIVRInput m_actions; + public: // I know it's an ugly hack to make them public to enable external // access, but I am too lazy to implement getters. - input::SteamIVRInput m_actions; SteamVRTabController m_steamVRTabController; ChaperoneTabController m_chaperoneTabController; MoveCenterTabController m_moveCenterTabController; @@ -106,6 +107,7 @@ public: // I know it's an ugly hack to make them public to enable external private: QPoint getMousePositionForEvent( vr::VREvent_Mouse_t mouse ); + void processInputBindings(); public: OverlayController( bool desktopMode, bool noSound, QQmlEngine& qmlEngine ); diff --git a/src/package_files/action_manifest.json b/src/package_files/action_manifest.json index 0b1a38c..d1e40ff 100644 --- a/src/package_files/action_manifest.json +++ b/src/package_files/action_manifest.json @@ -7,7 +7,22 @@ ], "actions": [ { - "name": "/actions/main/in/PlayNextTrack", + "name": "/actions/main/in/NextTrack", + "requirement": "optional", + "type": "boolean" + }, + { + "name": "/actions/main/in/PreviousTrack", + "requirement": "optional", + "type": "boolean" + }, + { + "name": "/actions/main/in/PausePlayTrack", + "requirement": "optional", + "type": "boolean" + }, + { + "name": "/actions/main/in/StopTrack", "requirement": "optional", "type": "boolean" } @@ -22,9 +37,12 @@ { "language_tag": "en", - "/actions/main" : "My Game Actions", + "/actions/main" : "Advanced Settings Actions", - "/actions/main/in/PlayNextTrack" : "Play Next Track" + "/actions/main/in/NextTrack" : "Play Next Track", + "/actions/main/in/PreviousTrack" : "Play Previous Track", + "/actions/main/in/PausePlayTrack" : "Pause/Play Track", + "/actions/main/in/StopTrack" : "Stop Track" } ] } \ No newline at end of file diff --git a/src/package_files/default_action_manifests/vive_defaults.json b/src/package_files/default_action_manifests/vive_defaults.json index 3e2094c..22e600c 100644 --- a/src/package_files/default_action_manifests/vive_defaults.json +++ b/src/package_files/default_action_manifests/vive_defaults.json @@ -3,40 +3,12 @@ "app_key" : "matzman666.advancedsettings", "bindings" : { "/actions/main" : { - "sources" : [ - { - "inputs" : { - "click" : { - "output" : "/actions/main/in/playnexttrack" - } - }, - "mode" : "button", - "path" : "/user/hand/left/input/application_menu" - }, - { - "inputs" : { - "click" : { - "output" : "/actions/main/in/playnexttrack" - } - }, - "mode" : "button", - "path" : "/user/hand/right/input/application_menu" - }, - { - "inputs" : { - "click" : { - "output" : "/actions/main/in/playnexttrack" - } - }, - "mode" : "button", - "path" : "/user/hand/right/input/grip" - } - ] + "sources" : [] } }, "controller_type" : "vive_controller", - "description" : "", - "name" : "My My Test configuration for Vive Controller", + "description" : "Nothing has been bound by default.", + "name" : "Empty Bindings (default)", "options" : {}, "simulated_actions" : [] }