Added missing launcher
[mupen64plus-pandora.git] / source / mupen64plus-input-sdl / src / autoconfig.c
CommitLineData
48d52ab5 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus-input-sdl - autoconfig.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2009-2013 Richard Goedeken *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22#include <string.h>
23
24#include "m64p_types.h"
25#include "m64p_config.h"
26#include "osal_preproc.h"
27#include "autoconfig.h"
28#include "plugin.h"
29
30/* local definitions */
31#define INI_FILE_NAME "InputAutoCfg.ini"
32typedef struct {
33 m64p_handle pSrc;
34 m64p_handle pDst;
35} SCopySection;
36
37/* local functions */
38static char *StripSpace(char *pIn)
39{
40 char *pEnd = pIn + strlen(pIn) - 1;
41
42 while (*pIn == ' ' || *pIn == '\t' || *pIn == '\r' || *pIn == '\n')
43 pIn++;
44
45 while (pIn <= pEnd && (*pEnd == ' ' || *pEnd == '\t' || *pEnd == '\r' || *pEnd == '\n'))
46 *pEnd-- = 0;
47
48 return pIn;
49}
50
51static void CopyParamCallback(void * context, const char *ParamName, m64p_type ParamType)
52{
53 SCopySection *pCpyContext = (SCopySection *) context;
54 int paramInt;
55 float paramFloat;
56 char paramString[1024];
57
58 // handle the parameter copy depending upon type
59 switch (ParamType)
60 {
61 case M64TYPE_INT:
62 case M64TYPE_BOOL:
63 if (ConfigGetParameter(pCpyContext->pSrc, ParamName, ParamType, &paramInt, sizeof(int)) == M64ERR_SUCCESS)
64 ConfigSetParameter(pCpyContext->pDst, ParamName, ParamType, &paramInt);
65 break;
66 case M64TYPE_FLOAT:
67 if (ConfigGetParameter(pCpyContext->pSrc, ParamName, ParamType, &paramFloat, sizeof(float)) == M64ERR_SUCCESS)
68 ConfigSetParameter(pCpyContext->pDst, ParamName, ParamType, &paramFloat);
69 break;
70 case M64TYPE_STRING:
71 if (ConfigGetParameter(pCpyContext->pSrc, ParamName, ParamType, paramString, 1024) == M64ERR_SUCCESS)
72 ConfigSetParameter(pCpyContext->pDst, ParamName, ParamType, paramString);
73 break;
74 default:
75 // this should never happen
76 DebugMessage(M64MSG_ERROR, "Unknown source parameter type %i in copy callback", (int) ParamType);
77 return;
78 }
79}
80
81/* global functions */
82int auto_copy_inputconfig(const char *pccSourceSectionName, const char *pccDestSectionName, const char *sdlJoyName)
83{
84 SCopySection cpyContext;
85
86 if (ConfigOpenSection(pccSourceSectionName, &cpyContext.pSrc) != M64ERR_SUCCESS)
87 {
88 DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: Couldn't open source config section '%s' for copying", pccSourceSectionName);
89 return 0;
90 }
91
92 if (ConfigOpenSection(pccDestSectionName, &cpyContext.pDst) != M64ERR_SUCCESS)
93 {
94 DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: Couldn't open destination config section '%s' for copying", pccDestSectionName);
95 return 0;
96 }
97
98 // set the 'name' parameter
99 if (sdlJoyName != NULL)
100 {
101 if (ConfigSetParameter(cpyContext.pDst, "name", M64TYPE_STRING, sdlJoyName) != M64ERR_SUCCESS)
102 {
103 DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: Couldn't set 'name' parameter to '%s' in section '%s'", sdlJoyName, pccDestSectionName);
104 return 0;
105 }
106 }
107
108 // the copy gets done by the callback function
109 if (ConfigListParameters(cpyContext.pSrc, (void *) &cpyContext, CopyParamCallback) != M64ERR_SUCCESS)
110 {
111 DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: parameter list copy failed");
112 return 0;
113 }
114
115 return 1;
116}
117
118int auto_set_defaults(int iDeviceIdx, const char *joySDLName)
119{
120 FILE *pfIn;
121 m64p_handle pConfig = NULL;
122 const char *CfgFilePath = ConfigGetSharedDataFilepath(INI_FILE_NAME);
123 enum { E_NAME_SEARCH, E_NAME_FOUND, E_PARAM_READ } eParseState;
124 char *pchIni, *pchNextLine, *pchCurLine;
125 long iniLength;
126 int ControllersFound = 0;
127
128 /* if we couldn't get a name (no joystick plugged in to given port), then return with a failure */
129 if (joySDLName == NULL)
130 return 0;
131 /* if we couldn't find the shared data file, dump an error and return */
132 if (CfgFilePath == NULL || strlen(CfgFilePath) < 1)
133 {
134 DebugMessage(M64MSG_ERROR, "Couldn't find config file '%s'", INI_FILE_NAME);
135 return 0;
136 }
137
138 /* read the input auto-config .ini file */
139 pfIn = fopen(CfgFilePath, "rb");
140 if (pfIn == NULL)
141 {
142 DebugMessage(M64MSG_ERROR, "Couldn't open config file '%s'", CfgFilePath);
143 return 0;
144 }
145 fseek(pfIn, 0L, SEEK_END);
146 iniLength = ftell(pfIn);
147 fseek(pfIn, 0L, SEEK_SET);
148 pchIni = (char *) malloc(iniLength + 1);
149 if (pchIni == NULL)
150 {
151 DebugMessage(M64MSG_ERROR, "Couldn't allocate %li bytes for config file '%s'", iniLength, CfgFilePath);
152 fclose(pfIn);
153 return 0;
154 }
155 if (fread(pchIni, 1, iniLength, pfIn) != iniLength)
156 {
157 DebugMessage(M64MSG_ERROR, "File read failed for %li bytes of config file '%s'", iniLength, CfgFilePath);
158 free(pchIni);
159 fclose(pfIn);
160 return 0;
161 }
162 fclose(pfIn);
163 pchIni[iniLength] = 0;
164
165 /* parse the INI file, line by line */
166 pchNextLine = pchIni;
167 eParseState = E_NAME_SEARCH;
168 while (pchNextLine != NULL && *pchNextLine != 0)
169 {
170 char *pivot = NULL;
171 /* set up character pointers */
172 pchCurLine = pchNextLine;
173 pchNextLine = strchr(pchNextLine, '\n');
174 if (pchNextLine != NULL)
175 *pchNextLine++ = 0;
176 pchCurLine = StripSpace(pchCurLine);
177
178 /* handle blank/comment lines */
179 if (strlen(pchCurLine) < 1 || *pchCurLine == ';' || *pchCurLine == '#')
180 continue;
181
182 /* handle section (joystick name in ini file) */
183 if (*pchCurLine == '[' && pchCurLine[strlen(pchCurLine)-1] == ']')
184 {
185 char Word[64];
186 char *wordPtr;
187 int joyFound = 1;
188
189 if (eParseState == E_PARAM_READ)
190 {
191 /* we've finished parsing all parameters for the discovered input device */
192 free(pchIni);
193 return ControllersFound;
194 }
195 else if (eParseState == E_NAME_FOUND)
196 {
197 /* this is an equivalent device name to the one we're looking for (and found); keep looking for parameters */
198 continue;
199 }
200 /* we need to look through the device name word by word to see if it matches the joySDLName that we're looking for */
201 pchCurLine[strlen(pchCurLine)-1] = 0;
202 wordPtr = StripSpace(pchCurLine + 1);
203 /* first, if there is a preceding system name in this .ini device name, and the system matches, then strip out */
204#if defined(__unix__)
205 if (strncmp(wordPtr, "Unix:", 5) == 0)
206 wordPtr = StripSpace(wordPtr + 5);
207#endif
208#if defined(__linux__)
209 if (strncmp(wordPtr, "Linux:", 6) == 0)
210 wordPtr = StripSpace(wordPtr + 6);
211#endif
212#if defined(__APPLE__)
213 if (strncmp(wordPtr, "OSX:", 4) == 0)
214 wordPtr = StripSpace(wordPtr + 4);
215#endif
216#if defined(WIN32)
217 if (strncmp(wordPtr, "Win32:", 6) == 0)
218 wordPtr = StripSpace(wordPtr + 6);
219#endif
220 /* search in the .ini device name for all the words in the joystick name. If any are missing, then this is not the right joystick model */
221 while (wordPtr != NULL && strlen(wordPtr) > 0)
222 {
223 char *nextSpace = strchr(wordPtr, ' ');
224 if (nextSpace == NULL)
225 {
226 strncpy(Word, wordPtr, 63);
227 Word[63] = 0;
228 wordPtr = NULL;
229 }
230 else
231 {
232 int length = (int) (nextSpace - wordPtr);
233 if (length > 63) length = 63;
234 strncpy(Word, wordPtr, length);
235 Word[length] = 0;
236 wordPtr = nextSpace + 1;
237 }
238 if (strcasestr(joySDLName, Word) == NULL)
239 joyFound = 0;
240 }
241 /* if we found the right joystick, then open up the core config section to store parameters and set the 'device' param */
242 if (joyFound)
243 {
244 char SectionName[32];
245 sprintf(SectionName, "AutoConfig%i", ControllersFound);
246 if (ConfigOpenSection(SectionName, &pConfig) != M64ERR_SUCCESS)
247 {
248 DebugMessage(M64MSG_ERROR, "auto_set_defaults(): Couldn't open config section '%s'", SectionName);
249 free(pchIni);
250 return 0;
251 }
252 eParseState = E_NAME_FOUND;
253 ControllersFound++;
254 ConfigSetParameter(pConfig, "device", M64TYPE_INT, &iDeviceIdx);
255 }
256 continue;
257 }
258
259 /* handle parameters */
260 pivot = strchr(pchCurLine, '=');
261 if (pivot != NULL)
262 {
263 /* if we haven't found the correct section yet, just skip this */
264 if (eParseState == E_NAME_SEARCH)
265 continue;
266 eParseState = E_PARAM_READ;
267 /* otherwise, store this parameter in the current active joystick config */
268 *pivot++ = 0;
269 pchCurLine = StripSpace(pchCurLine);
270 pivot = StripSpace(pivot);
271 if (strcasecmp(pchCurLine, "plugin") == 0 || strcasecmp(pchCurLine, "device") == 0)
272 {
273 int iVal = atoi(pivot);
274 ConfigSetParameter(pConfig, pchCurLine, M64TYPE_INT, &iVal);
275 }
276 else if (strcasecmp(pchCurLine, "plugged") == 0 || strcasecmp(pchCurLine, "mouse") == 0)
277 {
278 int bVal = (strcasecmp(pivot, "true") == 0);
279 ConfigSetParameter(pConfig, pchCurLine, M64TYPE_BOOL, &bVal);
280 }
281 else
282 {
283 ConfigSetParameter(pConfig, pchCurLine, M64TYPE_STRING, pivot);
284 }
285 continue;
286 }
287
288 /* handle keywords */
289 if (pchCurLine[strlen(pchCurLine)-1] == ':')
290 {
291 /* if we haven't found the correct section yet, just skip this */
292 if (eParseState == E_NAME_SEARCH)
293 continue;
294 /* otherwise parse the keyword */
295 if (strcmp(pchCurLine, "__NextController:") == 0)
296 {
297 char SectionName[32];
298 /* if there are no more N64 controller spaces left, then exit */
299 if (ControllersFound == 4)
300 {
301 free(pchIni);
302 return ControllersFound;
303 }
304 /* otherwise go to the next N64 controller */
305 sprintf(SectionName, "AutoConfig%i", ControllersFound);
306 if (ConfigOpenSection(SectionName, &pConfig) != M64ERR_SUCCESS)
307 {
308 DebugMessage(M64MSG_ERROR, "auto_set_defaults(): Couldn't open config section '%s'", SectionName);
309 free(pchIni);
310 return ControllersFound;
311 }
312 ControllersFound++;
313 ConfigSetParameter(pConfig, "device", M64TYPE_INT, &iDeviceIdx);
314 }
315 else
316 {
317 DebugMessage(M64MSG_ERROR, "Unknown keyword '%s' in %s", pchCurLine, INI_FILE_NAME);
318 }
319 continue;
320 }
321
322 /* unhandled line in .ini file */
323 DebugMessage(M64MSG_ERROR, "Invalid line in %s: '%s'", INI_FILE_NAME, pchCurLine);
324 }
325
326 if (eParseState == E_PARAM_READ)
327 {
328 /* we've finished parsing all parameters for the discovered input device, which is the last in the .ini file */
329 free(pchIni);
330 return ControllersFound;
331 }
332
333 free(pchIni);
334 return 0;
335}
336
337