1 /** @file directinput.cpp DirectInput for Windows.
2  * @ingroup input
3  *
4  * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
5  * @authors Copyright © 2005-2013 Daniel Swanson <danij@dengine.net>
6  *
7  * @par License
8  * GPL: http://www.gnu.org/licenses/gpl.html
9  *
10  * <small>This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2 of the License, or (at your
13  * option) any later version. This program is distributed in the hope that it
14  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details. You should have received a copy of the GNU
17  * General Public License along with this program; if not, write to the Free
18  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19  * 02110-1301 USA</small>
20  */
21 
22 #ifdef __CLIENT__
23 
24 #include "directinput.h"
25 #include "dd_winit.h"
26 #include <de/Log>
27 #include <doomsday/doomsdayapp.h>
28 
29 static LPDIRECTINPUT8 dInput;
30 static LPDIRECTINPUT dInput3;
31 
DirectInput_ErrorMsg(HRESULT hr)32 const char* DirectInput_ErrorMsg(HRESULT hr)
33 {
34     return hr == DI_OK ? "OK" : hr == DIERR_GENERIC ? "Generic error" : hr ==
35         DI_PROPNOEFFECT ? "Property has no effect" : hr ==
36         DIERR_INVALIDPARAM ? "Invalid parameter" : hr ==
37         DIERR_NOTINITIALIZED ? "Not initialized" : hr ==
38         DIERR_UNSUPPORTED ? "Unsupported" : hr ==
39         DIERR_NOTFOUND ? "Not found" : "?";
40 }
41 
DirectInput_Init(void)42 int DirectInput_Init(void)
43 {
44     HRESULT hr;
45 
46     if(dInput || dInput3) return true;
47 
48     // Create the DirectInput interface instance. Try version 8 first.
49     if(FAILED(hr = CoCreateInstance(CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
50                                     IID_IDirectInput8, (LPVOID*)&dInput)) ||
51        FAILED(hr = dInput->Initialize((HINSTANCE) DoomsdayApp::app().moduleHandle(), DIRECTINPUT_VERSION)))
52     {
53         LOGDEV_INPUT_ERROR("DirectInput 8 init failed (0x%x)") << hr;
54 
55         // Try the older version 3 interface instead.
56         // I'm not sure if this works correctly.
57         if(FAILED(hr = CoCreateInstance(CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
58                                         IID_IDirectInput2W, (LPVOID*)&dInput3)) ||
59            FAILED(hr = dInput3->Initialize((HINSTANCE) DoomsdayApp::app().moduleHandle(), 0x0300)))
60         {
61             LOGDEV_INPUT_ERROR("Failed to create DirectInput 3 object (0x%x)") << hr;
62             return false;
63         }
64 
65         LOG_INPUT_NOTE("Using DirectInput 3 as fallback");
66     }
67 
68     if(!dInput && !dInput3)
69     {
70         LOG_INPUT_ERROR("DirectInput init failed");
71         return false;
72     }
73 
74     return true;
75 }
76 
DirectInput_Shutdown(void)77 void DirectInput_Shutdown(void)
78 {
79     if(dInput)
80     {
81         IDirectInput_Release(dInput);
82         dInput = 0;
83     }
84     if(dInput3)
85     {
86         IDirectInput_Release(dInput3);
87         dInput3 = 0;
88     }
89 }
90 
DirectInput_IVersion8()91 LPDIRECTINPUT8 DirectInput_IVersion8()
92 {
93     return dInput;
94 }
95 
DirectInput_IVersion3()96 LPDIRECTINPUT DirectInput_IVersion3()
97 {
98     return dInput3;
99 }
100 
DirectInput_KillDevice(LPDIRECTINPUTDEVICE8 * dev)101 void DirectInput_KillDevice(LPDIRECTINPUTDEVICE8* dev)
102 {
103     if(*dev) (*dev)->Unacquire();
104     I_SAFE_RELEASE(*dev);
105 }
106 
107 #endif // __CLIENT__
108