1#include <stdio.h>
  2#include <stdlib.h>
  3#include <stdarg.h>
  4#include <getopt.h>
  5#include <pthread.h>
  6
  7#include "version.h"
  8#include "midi.h"
  9#include "synth.h"
 10#include "interface.h"
 11#include "mutex.h"
 12
 13void help(const char *argv0) {
 14	printf("Usage: %s [options]\n"
 15			"\nAvailable options:\n"
 16			"  -n,--new                     creates a new song file\n"
 17			"  -l,--list                    list available devices\n"
 18			"  -c,--client=client:port      device client and port\n"
 19			"  -s,--soundfont=file.sf2      soundfont file\n"
 20			"  -p,--preset=1                soundfont preset\n"
 21			"  -h,--help                    this help\n"
 22			"  -v,--version                 show version\n",
 23			argv0);
 24}
 25
 26int main(int argc, char *argv[]) {
 27	const char short_options[] = "n:lc:s:p:hv";
 28	const struct option long_options[] = {
 29		{ "new", 1, NULL, 'n' },
 30		{ "list", 0, NULL, 'l' },
 31		{ "client", 1, NULL, 'c' },
 32		{ "soundfont", 1, NULL, 's' },
 33		{ "preset", 0, NULL, 'p' },
 34		{ "help", 0, NULL, 'h' },
 35		{ "version", 0, NULL, 'v' },
 36		{ 0 },
 37	};
 38
 39	char *new_song_name = NULL;
 40	char *port_name = NULL;
 41	char *soundfont_file = NULL;
 42	int soundfont_preset = 0;
 43
 44	int opt;
 45	while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
 46		switch (opt) {
 47			case 'n':
 48				new_song_name = optarg;
 49			case 'l':
 50				fprintf(stderr, "List feature is NOT implemented yet.\n");
 51				return 0;
 52			case 'c':
 53				port_name = optarg;
 54				break;
 55			case 's':
 56				soundfont_file = optarg;
 57				break;
 58			case 'p':
 59				soundfont_preset = atoi(optarg);
 60				break;
 61			case 'h':
 62				help(argv[0]);
 63				return 0;
 64			case 'v':
 65				fprintf(stdout, "ttdaw version %s\n", VERSION);
 66				fprintf(stdout, "Website: %s.\n", WEBSITE);
 67				fprintf(stdout, "%s\n", LICENSE);
 68				fprintf(stdout, "%s\n", WARRANTY);
 69				fprintf(stdout, "\n%s\n", AUTHOR);
 70				return 0;
 71			default:
 72				fprintf(stdout, "Missing options. Check help.\n");
 73				return 0;
 74		}
 75	}
 76
 77	if (new_song_name != NULL) {
 78		fprintf(stdout, "Creating new song file with name %s\n", new_song_name);
 79		return 0;
 80	}
 81
 82	if (port_name == NULL || soundfont_file == NULL || soundfont_preset < 0) {
 83		fprintf(stdout, "Missing options. Check help.\n");
 84		fprintf(stdout, "Port, soundfile and preset are required fields.\n");
 85		return 1;
 86	}
 87
 88	fprintf(stdout, "> Device port:   %s\n", port_name);
 89	fprintf(stdout, "> Soundfont:     %s\n", soundfont_file);
 90	fprintf(stdout, "> SF preset:     %d\n", soundfont_preset);
 91	fprintf(stdout, "> Song name:     %s\n", new_song_name);
 92
 93	// Create mutex.
 94	initialize_mutex();	
 95
 96	// Create UI thread.
 97	pthread_t interface_thread;
 98	InterfaceArgs interface_args = {
 99		.soundfont_file = soundfont_file,
100		.soundfont_preset = soundfont_preset,
101	};
102
103	if (pthread_create(&interface_thread, NULL, interface, (void*)&interface_args) != 0) {
104		fprintf(stderr, "Error creating interface thread\n");
105		return 1;
106	}
107
108	// Create synth thread.
109	pthread_t synth_thread;
110	SynthArgs synth_args = {
111		.soundfont_file = soundfont_file,
112		.soundfont_preset = soundfont_preset,
113	};
114
115	if (pthread_create(&synth_thread, NULL, synth, (void*)&synth_args) != 0) {
116		fprintf(stderr, "Error creating synth thread\n");
117		return 1;
118	}
119
120	// Create MIDI thread.
121	pthread_t midi_thread;
122	MidiArgs midi_args = { port_name };
123
124	if (pthread_create(&midi_thread, NULL, midi, (void*)&midi_args) != 0) {
125		fprintf(stderr, "Error creating midi thread\n");
126		return 1;
127	}
128
129	// Start threads.
130	pthread_join(interface_thread, NULL);
131	pthread_join(midi_thread, NULL);
132	pthread_join(synth_thread, NULL);
133
134	// Destroy mutex.
135	destroy_mutex();
136
137	fprintf(stdout, "Exiting...\n");
138	return 0;
139}
140