1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
main(int,char **)19 
20     dumb_c.c
21     Minimal control mode -- no interaction, just prints out messages.
22 */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif /* HAVE_CONFIG_H */
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #ifndef NO_STRING_H
31 #include <string.h>
32 #else
33 #include <strings.h>
34 #endif
35 
36 #include "timidity.h"
37 #include "common.h"
38 #include "output.h"
39 #include "controls.h"
40 #include "instrum.h"
41 #include "playmidi.h"
42 #include "readmidi.h"
43 #ifdef __W32__
44 #include "wrd.h"
45 #endif /* __W32__ */
46 
47 static int ctl_open(int using_stdin, int using_stdout);
48 static void ctl_close(void);
49 static int ctl_read(int32 *valp);
50 static int cmsg(int type, int verbosity_level, char *fmt, ...);
51 static void ctl_total_time(long tt);
52 static void ctl_file_name(char *name);
53 static void ctl_current_time(int ct);
54 static void ctl_metronome(int, int);
55 static void ctl_lyric(int lyricid);
56 static void ctl_event(CtlEvent *e);
57 
58 /**********************************/
59 /* export the interface functions */
60 
61 #define ctl dumb_control_mode
62 
63 ControlMode ctl=
64 {
65     "dumb interface", 'd',
66     "dumb",
67     1,0,0,
68     0,
69     ctl_open,
70     ctl_close,
71     dumb_pass_playing_list,
72     ctl_read,
73     NULL,
74     cmsg,
75     ctl_event
76 };
77 
78 static uint32 cuepoint = 0;
79 static int cuepoint_pending = 0;
80 
81 static int curr_secs, curr_meas, curr_beat;
82 
83 static FILE *outfp;
84 int dumb_error_count;
85 
86 /*ARGSUSED*/
87 static int ctl_open(int using_stdin, int using_stdout)
88 {
89   if(using_stdout)
90     outfp=stderr;
91   else
92     outfp=stdout;
93   ctl.opened=1;
94   return 0;
95 }
96 
97 static void ctl_close(void)
98 {
99   fflush(outfp);
100   ctl.opened=0;
101 }
102 
103 static int ctl_read(int32 *valp)
104 {
105 	if (cuepoint_pending) {
106 		*valp = cuepoint;
107 		cuepoint_pending = 0;
108 		return RC_FORWARD;
109 	}
110   return RC_NONE;
111 }
112 
113 static int cmsg(int type, int verbosity_level, char *fmt, ...)
114 {
115   va_list ap;
116 
117   if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
118       ctl.verbosity<verbosity_level)
119     return 0;
120   va_start(ap, fmt);
121   if(type == CMSG_WARNING || type == CMSG_ERROR || type == CMSG_FATAL)
122       dumb_error_count++;
123   if (!ctl.opened)
124     {
125       vfprintf(stderr, fmt, ap);
126       fputs(NLS, stderr);
127     }
128   else
129     {
130       vfprintf(outfp, fmt, ap);
131       fputs(NLS, outfp);
132       fflush(outfp);
133     }
134   va_end(ap);
135   return 0;
136 }
137 
138 static void ctl_total_time(long tt)
139 {
140   int mins, secs;
141   if (ctl.trace_playing)
142     {
143       secs=(int)(tt/play_mode->rate);
144       mins=secs/60;
145       secs-=mins*60;
146       cmsg(CMSG_INFO, VERB_NORMAL,
147 	   "Total playing time: %3d min %02d s", mins, secs);
148     }
149 }
150 
151 static void ctl_file_name(char *name)
152 {
153   if (ctl.verbosity>=0 || ctl.trace_playing)
154       cmsg(CMSG_INFO, VERB_NORMAL, "Playing %s", name);
155 }
156 
157 static void ctl_current_time(int secs)
158 {
159   int mins, meas, beat;
160   static int prev_secs = -1;
161 
162 #ifdef __W32__
163 	  if(wrdt->id == 'w')
164 	    return;
165 #endif /* __W32__ */
166   if (ctl.trace_playing && secs != prev_secs)
167     {
168       curr_secs = prev_secs = secs;
169       mins=secs/60;
170       secs-=mins*60;
171       meas = curr_meas, beat = curr_beat;
172       fprintf(outfp, "\r%3d:%02d  %03d.%02d", mins, secs, meas, beat);
173       fflush(outfp);
174     }
175 }
176 
177 static void ctl_metronome(int meas, int beat)
178 {
179 	int mins, secs;
180 	static int prev_meas = -1, prev_beat = -1;
181 
182 #ifdef __W32__
183 	if (wrdt->id == 'w')
184 		return;
185 #endif /* __W32__ */
186 	if (ctl.trace_playing && (meas != prev_meas || beat != prev_beat)) {
187 		mins = curr_secs / 60, secs = curr_secs % 60;
188 		curr_meas = prev_meas = meas, curr_beat = prev_beat = beat;
189 		fprintf(outfp, "\r%3d:%02d  %03d.%02d", mins, secs, meas, beat);
190 		fflush(outfp);
191 	}
192 }
193 
194 static void ctl_lyric(int lyricid)
195 {
196     char *lyric;
197 
198     lyric = event2string(lyricid);
199     if(lyric != NULL)
200     {
201 	if(lyric[0] == ME_KARAOKE_LYRIC)
202 	{
203 	    if(lyric[1] == '/' || lyric[1] == '\\')
204 	    {
205 		fprintf(outfp, "\n%s", lyric + 2);
206 		fflush(outfp);
207 	    }
208 	    else if(lyric[1] == '@')
209 	    {
210 		if(lyric[2] == 'L')
211 		    fprintf(outfp, "\nLanguage: %s\n", lyric + 3);
212 		else if(lyric[2] == 'T')
213 		    fprintf(outfp, "Title: %s\n", lyric + 3);
214 		else
215 		    fprintf(outfp, "%s\n", lyric + 1);
216 	    }
217 	    else
218 	    {
219 		fputs(lyric + 1, outfp);
220 		fflush(outfp);
221 	    }
222 	}
223 	else
224 	{
225 	    if(lyric[0] == ME_CHORUS_TEXT || lyric[0] == ME_INSERT_TEXT)
226 		fprintf(outfp, "\r");
227 	    fputs(lyric + 1, outfp);
228 	    fflush(outfp);
229 	}
230     }
231 }
232 
233 static void ctl_event(CtlEvent *e)
234 {
235     switch(e->type)
236     {
237       case CTLE_NOW_LOADING:
238 	ctl_file_name((char *)e->v1);
239 	break;
240       case CTLE_PLAY_START:
241 	ctl_total_time(e->v1);
242 	break;
243 	case CTLE_CUEPOINT:
244 		cuepoint = e->v1;
245 		cuepoint_pending = 1;
246 		break;
247       case CTLE_CURRENT_TIME:
248 	ctl_current_time((int)e->v1);
249 	break;
250 	case CTLE_METRONOME:
251 		ctl_metronome(e->v1, e->v2);
252 		break;
253       #ifndef CFG_FOR_SF
254       case CTLE_LYRIC:
255 	ctl_lyric((int)e->v1);
256 	break;
257       #endif
258     }
259 }
260 
261 /*
262  * interface_<id>_loader();
263  */
264 ControlMode *interface_d_loader(void)
265 {
266     return &ctl;
267 }
268