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