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" : [] }