Since I found out that both Linux and my cheap USB joystick support force feedback, I'm interested in developing support for force feedback, or for haptic devices for short, also in Allegro. Now, on the PC platform, and certainly on Linux, almost no game uses haptic effects since no one knows how to program them. So support for haptic devices in Allegro would be nice. Also, SDL2 will also support haptic effects, so that's another reason I don't want Allegro to fall behind.
Anyway, I started work on this, but Thomas suggested that I first post the API I suggest here, so we can discuss and improve it. So please read this proposal for allegro5/haptic.h and tell me what you like, dislike and find unclear about it. Without more ado, here is the content of the file (also attached for use at your leasure).
One "danger" with these things is always that you write for one platform and then other platforms do things completely differently. You end up with a "biased" api. If you haven't already, I think you should look at Windows and Mac OS X and see how things are done there (even if you can't write drivers for those.) Then find a common set of functions and an API that is not targetted at a single platform.
NOTE: You may have already done this. I see a lot of very specific information here and that made me wonder if this wasn't just a thin wrapper over Linux apis.
Actually I'm guilty as charged there.
I don't have access to windows or mac OS-X, so to get some ideas of who to structure the API, I had to take a look at the SDL 2 sources (which are under the same license as Allegro, so no problem there). They too use a Linux-ish API as the smallest common denominator for most platforms . So I went for that with some nuances, such as using doubles to get device independent value for time , and relative values for intensity in there.
But I also know from SDL2 that it's possible to fit Windows and OS-X into this Linux-ish API, so I thought it would be OK. But if you have better ideas, then please do make suggestions.
I'll probably only be able to supply a Linux driver anyway, so I'd love to hear from people who want to implement te Windows or OS-X, or Iphone, or Android drivers for this and I'd like those people to tell me how we could modify this proposal so it will make it easy for them to write their drivers.
But I also know from SDL2 that it's possible to fit Windows and OS-X into this Linux-ish API, so I thought it would be OK.
If that's the case then it's probably OK. BTW, you don't need a computer running Windows or OS X to look at the APIs. MSDN and http://developer.apple.com have documentation online.
Well yes, but I don' t use SDL exactly because I like the Allegro API better, so their API doesn't have to be the end-all be-all. If possible I'd like an API that is easier to use than SDL.
It's true, I should RTFM, but since I don't have a chance to test the other platforms, I doubt I would learn much more from RTFM than from the SDL code. I'd rather listen to the opinion of people who had hands on experience with those API's. Or people who are willing to gain this experience.
To be blunt, Trent, would you be willing to do the Windows or OSX port of this? You can get a USB joystick that supports rumble cheaply and easily enough, and then you can try to make it work using the Windows or OSX API. Like that you'll get valuable hands-on experience and we'll be able to decide how too proceed with ALLEGRO_HAPTICS much better.
I can do Windows and OS X, but I may not have a lot of time to invest in them. I'll do my best. I guess I'll have a look on MSDN first and see what's available.
Thanks a lot! I know you are busy with your game project, but I think for an action RPG, rumble effects certainly will be an extra selling point. Even if you can't write the whole driver, your explorations will hopefully shed some light on the right approach.
I'll share with you the whole patch of all other changes I made versus Allegro git so far while I was working on the Linux driver, if and when you need it, so feel free to request it whenever.
Branches are cheap in git right? Is there any reason we can't create a branch for developing this (to anyone who knows)?
beoran, these two pages hold most of the key information on force feedback with DirectInput:
http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.idirectinputdevice8.idirectinputdevice8.createeffect(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.idirectinputeffect.idirectinputeffect.setparameters(v=vs.85).aspx
Maybe you can tell me what out of this is common between your header and this. We can then try and make something that works well with stuff in common from them. For things that are in one but not the other, we can optionally drop them or keep them with fallbacks to something close where not supported.
EDIT2: After reading over your API fully and comparing it to DirectInput, it's mostly the same. I think there are a few types of effect that are missing in DirectInput and I didn't see anything about replays (if there is no replay in DirectInput I think we could put the onus on the user to replay effects, I'm not sure about this though.)
One thing I think that should be done is to somehow merge this with the joystick (and mouse?) apis somewhat. Like perhaps we could have a function like ALLEGRO_JOYSTICK *al_get_haptic_joystick and maybe the reverse.
OK, I'll set up my allegro branch at github for this, it might be tomorrow or Monday though before I get this done.
I quicly read the info linked too and it seems Directinput supports a few effects that Linux doesn't, and generally formats it's parameters differently, and is somewhat more convoluted. Especially when it comes to the position of the effect. Linux only supports an angle, (or 2 carthesian axes for a condition effect, IIRC), but DI supports much more. My idea was to only support spherical coordinates , and let the divers translate those as needed.
The Directinput API does allow on to upload, play and stop a sample, but it doesn't give you a "play id" like Linux does, you have to use the effect object, which means you can't reuse the object for different replays. This means that it may be easier to implement the API if we drop the play id and always use an ALLEGRO_HAPTIC_EFFECT * to control playback and stopping:
What you say?
Looks ok. DirectInput doesn't have a "rumble" haptic, which one do you think is closest?
(probably just an oversight but does this need the effect parameter? AL_FUNC(bool, al_stop_all_haptic_effects , (ALLEGRO_HAPTIC
11*, ALLEGRO_HAPTIC_EFFECT * effect));)
Rumble is just a very simple "rumble" effect, normally you replace this by a periodic sine wave (or other supported wave) of the required amplitude. Actually, Linux supports rumble because the driver does an internal translation for you. I still want to have a "rumble" for the simples use case where all you want is a bit of vibration in the joystick.
Oh, and for integrating ALLEGRO_HAPTIC devices with joystick and mouse, I think
al_get_haptic_from_mouse and al_get_haptic_from_joystick should be enough for now. Normally I'd imagine you first install the joysticks and then enable the haptic effects on them. We could probably put that in the docs too and perhaps even require this, although I still haven't figured out yet how to make this work with the pluggable joysticks feature.
And yes, that was an oversight. The proper signature is of course
AL_FUNC(bool, al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *));
I think the ALLEGRO_HAPTIC for any joystick should behave exactly like the ALLEGRO_JOYSTICKs. If it's unplugged or one is plugged in the current state remains valid. Those devices become usable/unusable once you call al_reconfigure_joysticks. I guess with mice or other devices we just not support hotplugging at least at this time.
And I agree that having a simple "rumble" effect is a good idea.
Yes, I see the point about al_reconfigure_joysticks. Perhhaps that's what al_reconfigure_haptics will do on the side of the haptic devices then?
Oh, and it went easier than I thought, I set up a copy of the Allegro development branch on Github. You need the "haptics" branch specifically, get it here:
https://github.com/beoran/allegro/tree/haptic
Ah git... It's sometimes a bit difficult to use, but in functionality, it's "king"!
Depends. Besides gamepads, what other haptic devices are there that will be supported? DirectInput only supports haptics on gamepads. On Linux we could do something like we do for joysticks already, but I don't know if hot pluggable haptic devices are as important as joysticks. Do other haptic devices on Linux get /dev/input/js* devices or something else? If so they'd probably be treated like joysticks with no buttons or whatever, and al_reconfigure_joysticks would take care of them automatically.
Checking out the code now.
EDIT: Couldn't complete the checkout. Got this error:
warning: remote HEAD refers to nonexistent ref, unable to checkout.
In linux, any input device can have haptic capabilities. So it's not linked to /dev/input/js0 at all, really. At least in theory, linux can have haptic keyboards, haptic trackerballs, haptic mise, haptic tablets, haptic touch screens, etc.
Another reason why haptic devices may not be integrated in joystics is on mobile platforms. Iphones and android can vibrate the whole phone, which isn't connected to the input. I though this should probably be modeled in Allegro as a haptic device too.
And the code isn't in compiling state, sorry for that. I just blasted it there quickly so we could "git" going. :p
Edit: to solve your git problem, after clning the repository, go into the seemingly empty cloned allegro subdir and do
git checkout 653125e2e3c80953d153c0a3f34326e940e8cadc
git checkout -b haptic
To get the repository in working state.
Ok, but the error is from git. I can't clone the repository.
I tested it, if you do git clone and then get that message, you should find a seemingly empty allegro directory. That means the cloning actually worked, just the checkout didn't.
Necause git's not able to find the right branch (it expects master but that doesn't exist), it checks out nothing and leaves the allegro directory seemingly empty. So you must manually check out the latest revision and tell it that is the haptic branch.
(I only looked at this briefly so far)
You provide a filled-in effect structure to al_upload_haptic_effect, but then you must provide the same address to al_play_haptic_effect? I think the previous design was cleaner, where the ALLEGRO_HAPTIC object owns the effect after uploading, and returns a handle for you to work with.
Yeah that makes sense to me. I just couldn't articulate it.
Iphones and android can vibrate the whole phone, which isn't connected to the input. I though this should probably be modeled in Allegro as a haptic device too.
I agree.
OK, I'll reinstate the int handle based API. Or should I use a ALLEGRO_HAPTIC_PLAYBACK * , a bit like the sound API?
Maybe ALLEGRO_HAPTIC_EFFECT_ID (not a pointer) if we were to match the audio API.
Do we need the stuff to enumerate/reconfigure/get/release individual ALLEGRO_HAPTIC objects? I'm assuming that haptic devices could be a component of some other objects, mainly ALLEGRO_JOYSTICK. For vibrating the whole phone, we might use the ALLEGRO_DISPLAY as the parent (or introduce something different). This might simplify the API a bit.
I'll take another look at the audio API and try to see how I can match that best with an ALLEGRO_HAPTIC_EFFECT_ID.
As for simplifying the API, unfortunately, some haptic devices are not connected to another device such as a display, screen or a joystick. Think of the PS2 Rez "Trance Vibrator" or other similar haptic devices. We have to think of everything...
We have joy sticks.
Ah yes, joy sticks like these ones too:
http://therionorteline.files.wordpress.com/2012/09/usb-vibrator.jpg?w=1092
True, we could model such a no-input haptic device as a joystick (that does not return events), but I feel that that doesn't make much sense now if that makes sense. Also mice and keyboards can be haptic as well.
However, perhaps a few joystick wrapper functions could be useful, like say
al_joystick_upload_haptic_effect, al_joystick_upload_play_effect, etc?
Jokes aside, al_get_joystick_num_sticks/axes/buttons can return zero as well, once we update the documentation. How many zero-input devices are there anyway? (not counting gimmicks which only draw power from the USB port) I assume the Rez trance vibrator, specifically, is just another game controller to the OS.
Haptic keyboard/mouse can be handled as you had already.
Well, I can't say for all operating systems, but the Rez presents itself to Linux in the driver I know of as a device separate from the input, with a separate API. This may be a reason, though to disregard it for now.
However, I have to admit that for all other haptic devices I know of on Linux, the haptic capabilities are a part of the properties of a generic input device. Also, it's probably true that it will be easier for the people who use the API if they can get the haptic device handle directly from the desired device. So, I'll follow your suggestion.
I'll change the proposed API so haptic capabilities will be linked to existing input devices. And for the rare case of a haptic device that has no input capabilities, we'll make a virtual joystick that has no axes, or perhaps a al_joystic_is_pure_haptic(). Also this makes it possible to link the coordinate system of the haptic device to the axes the joystick actually has. It does mean that we have to modify the Linux joystick driver to scan more than just /dev/input/js* to get the "virtual joysticks".
So the way to get a haptic device handle will then be the following:
ALLEGRO_HAPTIC * al_get_haptic_from_joystick(ALLEGRO_JOYSTICK *); ALLEGRO_HAPTIC * al_get_haptic_from_keyboard(ALLEGRO_KEYBOARD *); ALLEGRO_HAPTIC * al_get_haptic_from_display(ALLEGRO_DISPLAY *); ALLEGRO_HAPTIC * al_get_haptic_from_mouse(ALLEGRO_MOUSE *); ALLEGRO_HAPTIC * al_get_haptic_from_touch_input(ALLEGRO_TOUCH_INPUT *);
Hmm, almost makes me wish we had some kind of generic ALLEGRO_INPUT_DEVICE...
Edit: here is the adjusted proposal for haptic.h, also with ALLEGRO_HAPTIC_EFFECT_ID to simplify play and stop.
Edit 2: I checked the X Windows mouse, display, and keyboard drivers, and the problem with them is that there is not trace to befound of the the underlying /dev/input/eventXX device. So there's no easy way to enable haptic support for them if any. The Linux joystick driver does have a fd of the input device that can be used to send haptic effects to, but all in all, it seems that the API I propose above could only be implemented relatively easily on on Linux for joysticks. For all other devices we'd have to scan all input devices and try to match them with the corresponding X Windows input... That seems convoluted. :/
We never access the underlying device files, as ostensibly X is still a network aware system, and keyboard and mouse could be on another machine. So we would probably wait the necessary support appears in X, or whatever replaces it.
(We could actually support joystick via XInput, but AFAIK no one really does so.)
OK, that's fair enough. I can live with the idea that on X, we'll only have haptic joysticks for the time being, and then only on Linux. In theory SDL 2 is more capable than this, but I can see in practice, the API above will suffice for a first implemenation of haptics on Allegro. GLFW, for example also has a similar limitation of haptics only for joysticks. On other platforms, non-joystick haptics (like Vibrate on Android) may still be defined using al_get_haptic_from_display, etc.
With the current driver joystick support on other *BSD/*nix systems does not work anyway. And I've been reading around a bit and it looks like on Linux we'll probably have also to support either Wayland or Mir, or both (or maybe nether and system nr 3 will come along). Those systems just boil down that we'll have to use /dev/input/eventXX for everything input related anyway. When that happens, we can enable haptic support for all these devices.
I'll start implementing the API above for Linux. I will have to refactor the Linux joystick driver a bit though since now the haptic driver will need to read the joysticks driver's internal details. Probably the same will be needed on other platforms too. But that's not a fundamental problem.