summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/portmidi/finddefaultlinux.c
blob: e59bd39437dde2d94a3035416aecf326cad8fd0b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* finddefault.c -- find_default_device() implementation
   Roger Dannenberg, Jan 2009
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "portmidi.h"

extern int pm_find_default_device(char *pattern, int is_input);

#define STRING_MAX 256

/* skip over spaces, return first non-space */
void skip_spaces(FILE *inf)
{
	char c;
	while (isspace(c = getc(inf))) ;
	ungetc(c, inf);
}

/* trim leading spaces and match a string */
int match_string(FILE *inf, char *s)
{
	skip_spaces(inf);
	while (*s && *s == getc(inf)) s++;
	return (*s == 0);
}


/* Parse preference files, find default device, search devices --
 */
PmDeviceID find_default_device(char *path, int input, PmDeviceID id)
/* path -- the name of the preference we are searching for
   input -- true iff this is an input device
   id -- current default device id
   returns matching device id if found, otherwise id
*/
{
	static char *pref_2 = (char *)"/.java/.userPrefs/";
	static char *pref_3 = (char *)"prefs.xml";
	char *pref_1 = getenv("HOME");
	char *full_name, *path_ptr;
	FILE *inf;
	int c, i;
	if (!pref_1) goto nopref; // cannot find preference file
	// full_name will be larger than necessary
	full_name  = malloc(strlen(pref_1) + strlen(pref_2) + strlen(pref_3) +
						strlen(path) + 2);
	strcpy(full_name, pref_1);
	strcat(full_name, pref_2);
	// copy all but last path segment to full_name
	if (*path == '/') path++; // skip initial slash in path
	path_ptr = strrchr(path, '/');
	if (path_ptr) { // copy up to slash after full_name
		path_ptr++;
		int offset = strlen(full_name);
		memcpy(full_name + offset, path, path_ptr - path);
		full_name[offset + path_ptr - path] = 0; // end of string
	} else {
		path_ptr = path;
	}
	strcat(full_name, pref_3);
	inf = fopen(full_name, "r");
	free(full_name);
	if (!inf) goto nopref; // cannot open preference file
	// We're not going to build or link in a full XML parser.
	// Instead, find the path string and quoute. Then, look for
	// "value", "=", quote. Then get string up to quote.
	while ((c = getc(inf)) != EOF) {
		char pref_str[STRING_MAX];
		if (c != '"') continue; // scan up to quote
		// look for quote string quote
		if (!match_string(inf, path_ptr)) continue; // path not found
		if (getc(inf) != '"') continue; // path not found, keep scanning
		if (!match_string(inf, (char *)"value")) goto nopref; // value not found
		if (!match_string(inf, (char *)"=")) goto nopref; // = not found
		if (!match_string(inf, (char *)"\"")) goto nopref; // quote not found
		// now read the value up to the close quote
		for (i = 0; i < STRING_MAX; i++) {
			if ((c = getc(inf)) == '"') break;
			pref_str[i] = c;
		}
		if (i == STRING_MAX) continue; // value too long, ignore
		pref_str[i] = 0;
		i = pm_find_default_device(pref_str, input);
		if (i != pmNoDevice) {
			id = i;
	}
		break;
	}
	nopref:
	return id;
}