aboutsummaryrefslogtreecommitdiffhomepage
path: root/midimonster.c
blob: d00f11611e32451f3a484ba12c0bc70ce57ac147 (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <string.h>
#include <signal.h>
#include <stdarg.h>
#ifndef _WIN32
	#define MM_API __attribute__((visibility("default")))
#else
	#define MM_API __attribute__((dllexport))
#endif

#define BACKEND_NAME "cli"
#include "midimonster.h"
#include "core/core.h"
#include "core/config.h"

volatile static sig_atomic_t shutdown_requested = 0;

MM_API int log_printf(int level, char* module, char* fmt, ...){
	int rv = 0;
	va_list args;
	va_start(args, fmt);
	fprintf(stderr, "%s%s\t", level ? "debug/" : "", module);
	rv = vfprintf(stderr, fmt, args);
	va_end(args);
	return rv;
}

static void signal_handler(int signum){
	shutdown_requested = 1;
}

static void version(){
	printf("MIDIMonster %s\n", MIDIMONSTER_VERSION);
}

static int usage(char* fn){
	version();
	fprintf(stderr, "Usage:\n");
	fprintf(stderr, "\t%s <configfile>\n", fn);
	return EXIT_FAILURE;
}


static int platform_initialize(){
	#ifdef _WIN32
	unsigned error_mode = SetErrorMode(0);
	SetErrorMode(error_mode | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
	#endif
	return 0;
}

static int platform_shutdown(){
	#ifdef _WIN32
	DWORD processes;
	if(GetConsoleProcessList(&processes, 1) == 1){
		fprintf(stderr, "\nMIDIMonster is the last process in this console, please press any key to exit\n");
		HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
		SetConsoleMode(input, 0);
		FlushConsoleInputBuffer(input);
		WaitForSingleObject(input, INFINITE);
	}
	#endif
	return 0;
}

static int args_parse(int argc, char** argv, char** cfg_file){
	size_t u;
	for(u = 1; u < argc; u++){
		if(!strcmp(argv[u], "-v") || !strcmp(argv[u], "--version")){
			version();
			return 1;
		}
		else if(!strcmp(argv[u], "-i")){
			if(!argv[u + 1]){
				fprintf(stderr, "Missing instance override specification\n");
				return 1;
			}
			if(config_add_override(override_instance, argv[u + 1])){
				return 1;
			}
			u++;
		}
		else if(!strcmp(argv[u], "-b")){
			if(!argv[u + 1]){
				fprintf(stderr, "Missing backend override specification\n");
				return 1;
			}
			if(config_add_override(override_backend, argv[u + 1])){
				return 1;
			}
			u++;
		}
		else{
			//if nothing else matches, it's probably the configuration file
			*cfg_file = argv[u];
		}
	}

	return 0;
}

int main(int argc, char** argv){
	int rv = EXIT_FAILURE;
	char* cfg_file = DEFAULT_CFG;

	//parse commandline arguments
	if(args_parse(argc, argv, &cfg_file)){
		return EXIT_FAILURE;
	}

	version();
	if(platform_initialize()){
		fprintf(stderr, "Failed to perform platform-specific initialization\n");
		return EXIT_FAILURE;
	}

	//initialize backends
	if(core_initialize()){
		goto bail;
	}

	//read config
	if(config_read(cfg_file)){
		fprintf(stderr, "Failed to parse master configuration file %s\n", cfg_file);
		core_shutdown();
		return (usage(argv[0]) | platform_shutdown());
	}

	//start core
	if(core_start()){
		goto bail;
	}

	signal(SIGINT, signal_handler);

	//run the core loop
	while(!shutdown_requested){
		if(core_iteration()){
			goto bail;
		}
	}

	rv = EXIT_SUCCESS;
bail:
	core_shutdown();
	return rv;
}