Import jackctlmmc-0 (from released tarball)
[jackctlmmc.git] / main.c
blobde14af3050897fe401f0ed0572598d9e4d5e6167
1 #include <jack/jack.h>
2 #include <alsa/asoundlib.h>
3 #include <lash/lash.h>
5 #include <signal.h>
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
10 snd_seq_t * g_seq_ptr;
11 lash_client_t * g_lashc;
12 jack_client_t * g_jack_client;
14 /* a flag which will be set by our signal handler when it's time to exit */
15 int quit = 0;
17 /* the signal handler */
18 void
19 signalled(int signal)
21 quit = 1;
24 void
25 process_lash_event(lash_event_t * event_ptr)
27 enum LASH_Event_Type type;
28 const char * str;
30 type = lash_event_get_type(event_ptr);
31 str = lash_event_get_string(event_ptr);
33 switch (type)
35 case LASH_Quit:
36 printf("LASH_Quit received.\n");
37 g_lashc = NULL;
38 quit = 1;
39 break;
40 case LASH_Save_File:
41 case LASH_Restore_File:
42 case LASH_Save_Data_Set:
43 default:
44 printf("LASH Event. Type = %u, string = \"%s\"\n",
45 (unsigned int)type,
46 (str == NULL)?"":str);
50 void
51 process_lash_config(lash_config_t * config_ptr)
53 const char * key;
54 const void * data;
55 size_t data_size;
57 key = lash_config_get_key(config_ptr);
58 data = lash_config_get_value(config_ptr);
59 data_size = lash_config_get_value_size(config_ptr);
61 printf("LASH Config. Key = \"%s\"\n", key);
64 int
65 main(int argc, char *argv[])
67 int ret;
68 lash_event_t * lash_event_ptr;
69 lash_config_t * lash_config_ptr;
70 snd_seq_port_info_t * seq_port_info = NULL;
71 snd_seq_event_t * seq_event_ptr;
72 int npfd;
73 struct pollfd * pfd;
75 /* setup our signal handler signalled() above, so we can exit cleanly (see end of main()) */
76 signal(SIGINT, signalled);
78 /* LASH setup */
79 g_lashc = lash_init(
80 lash_extract_args(&argc, &argv),
81 "jackctlmmc",
83 LASH_PROTOCOL_VERSION);
85 if (g_lashc == NULL)
87 printf("Failed to connect to LASH. Session management will not occur.\n");
89 else
91 lash_event_ptr = lash_event_new_with_type(LASH_Client_Name);
92 lash_event_set_string(lash_event_ptr, "jackctlmmc");
93 lash_send_event(g_lashc, lash_event_ptr);
96 /* naturally we need to become a jack client :) */
97 g_jack_client = jack_client_new("jackctlmmc");
98 if (!g_jack_client)
100 printf("couldn't connect to jack server. Either it's not running or the client name is already taken\n");
101 goto exit;
104 lash_jack_client_name(g_lashc, "jackctlmmc");
106 /* ALSA sequencer initialisation */
107 ret = snd_seq_open(
108 &g_seq_ptr,
109 "default",
110 SND_SEQ_OPEN_INPUT,
112 if (ret < 0)
114 printf("Cannot open sequncer, %s\n", snd_strerror(ret));
115 goto close_jack;
118 snd_seq_set_client_name(g_seq_ptr, "jackctlmmc");
120 lash_alsa_client_id(g_lashc, snd_seq_client_id(g_seq_ptr));
122 snd_seq_port_info_alloca(&seq_port_info);
124 snd_seq_port_info_set_capability(
125 seq_port_info,
126 SND_SEQ_PORT_CAP_WRITE |
127 SND_SEQ_PORT_CAP_SUBS_WRITE);
128 snd_seq_port_info_set_type(
129 seq_port_info,
130 SND_SEQ_PORT_TYPE_APPLICATION);
131 snd_seq_port_info_set_midi_channels(seq_port_info, 16);
132 snd_seq_port_info_set_port_specified(seq_port_info, 1);
134 snd_seq_port_info_set_name(seq_port_info, "midi in");
135 snd_seq_port_info_set_port(seq_port_info, 0);
137 ret = snd_seq_create_port(g_seq_ptr, seq_port_info);
138 if (ret < 0)
140 printf("Error creating ALSA sequencer port, %s\n", snd_strerror(ret));
141 goto close_seq;
144 /* tell jack that we are ready to do our thing */
145 jack_activate(g_jack_client);
147 npfd = snd_seq_poll_descriptors_count(g_seq_ptr, POLLIN);
148 pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
149 snd_seq_poll_descriptors(g_seq_ptr, pfd, npfd, POLLIN);
151 /* wait until this app receives a SIGINT (i.e. press ctrl-c in the terminal) see signalled() above */
152 while(!quit)
154 if (poll(pfd, npfd, 250) > 0 && snd_seq_event_input(g_seq_ptr, &seq_event_ptr) >= 0)
156 if (seq_event_ptr->type == SND_SEQ_EVENT_SYSEX &&
157 seq_event_ptr->data.ext.len == 6 &&
158 ((unsigned char *)seq_event_ptr->data.ext.ptr)[0] == 0xF0 &&
159 ((unsigned char *)seq_event_ptr->data.ext.ptr)[1] == 0x7F &&
160 ((unsigned char *)seq_event_ptr->data.ext.ptr)[2] == 0x7F && /* All devices */
161 ((unsigned char *)seq_event_ptr->data.ext.ptr)[3] == 0x06 &&
162 ((unsigned char *)seq_event_ptr->data.ext.ptr)[5] == 0xF7)
164 switch (((char *)seq_event_ptr->data.ext.ptr)[4])
166 case 1: /* stop */
167 printf("MMC Stop -> JACK transport stop\n");
168 jack_transport_stop(g_jack_client);
169 break;
170 case 2: /* play */
171 printf("MMC Play -> JACK transport start\n");
172 jack_transport_start(g_jack_client);
173 break;
174 case 5: /* rewind */
175 printf("MMC Play -> JACK transport locate to 0\n");
176 jack_transport_locate(g_jack_client, 0);
177 break;
182 /* Process LASH events */
183 while ((lash_event_ptr = lash_get_event(g_lashc)) != NULL)
185 process_lash_event(lash_event_ptr);
186 lash_event_destroy(lash_event_ptr);
189 /* Process LASH configs */
190 while ((lash_config_ptr = lash_get_config(g_lashc)) != NULL)
192 process_lash_config(lash_config_ptr);
193 lash_config_destroy(lash_config_ptr);
197 /* so we shall quit, eh? ok, cleanup time. otherwise jack would probably produce an xrun
198 * on shutdown */
199 jack_deactivate(g_jack_client);
201 close_seq:
202 ret = snd_seq_close(g_seq_ptr);
203 if (ret < 0)
205 printf("Cannot close sequncer, %s\n", snd_strerror(ret));
208 close_jack:
209 /* shutdown cont. */
210 jack_client_close(g_jack_client);
212 exit:
213 return 0;