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