1 /*
2  * AutoZen
3  * Steven James <pyro@linuxlabs.com>
4  * Linux Labs http://www.linuxlabs.com
5  * http://www.linuxlabs.com/software/AutoZen.html
6  *
7  * This is Free software, licensed under the GNU Public License V2.
8  *
9  * Version: 2.1
10  */
11 
12 #include <stdio.h>
13 #include <math.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <time.h>
18 #include <sys/ioctl.h>
19 #include <sys/stat.h>
20 #include <pthread.h>
21 #include <gtk/gtk.h>
22 
23 
24 /* Messy, but should manage to include the OSS
25 	Headers for Linux and the various *BSDs
26 	+ Solaris. Thanks to Trevor Johnson for this */
27 
28 /* "The nice thing about standards..." */
29 #if defined (__FreeBSD__)
30 #include <sys/soundcard.h>
31 #else
32 #if defined (__NetBSD__) || defined (__OpenBSD__)
33 #include <soundcard.h>          /* OSS emulation */
34 #undef ioctl
35 #else
36 /* BSDI, Linux, Solaris */
37 #include <sys/soundcard.h>
38 #endif                          /* __NetBSD__ or __OpenBSD__ */
39 #endif                          /* __FreeBSD__ */
40 
41 //#define DEBUG
42 /////////////////////////////////////////////////////////////////////////
43 //
44 //		Global Widgets
45 //
46 /////////////////////////////////////////////////////////////////////////
47 GtkObject *adj_beat;
48 GtkWidget *scale_beat;
49 
50 GtkObject *adj_base;
51 GtkWidget *scale_base;
52 
53 GtkWidget *ClockTime;
54 GtkWidget *BeatFreq;
55 
56 GtkWidget *BaseFreq;
57 GtkWidget *VolLabel;
58 
59 GtkObject *adj_vol;
60 
61 GtkWidget *PhaseLabel;
62 GtkObject *adj_colorboxphase;
63 GtkWidget *scale_colorboxphase;
64 
65 GtkWidget *PlayPixWid;
66 GdkPixmap *PlayPix;
67 GdkBitmap *PlayBit;
68 
69 GdkPixmap *PausePix;
70 GdkBitmap *PauseBit;
71 
72 GdkPixmap *PausedPix;
73 GdkBitmap *PausedBit;
74 
75 #define COLORBOX_X 640
76 #define COLORBOX_Y 480
77 
78 GtkWidget *ColorBox;
79 GtkStyle  *ColorBox_default_style, *ColorBox_new_style;
80 GdkColor  ColorBox_new_color = {0, 0x8000, 0x0, 0x8000};
81 gint ColorBoxTOhandle;
82 
83 #ifdef COLORBOX_DEFAULT_ON
84 int ColorBoxX = COLORBOX_X;
85 int ColorBoxY = COLORBOX_Y;
86 
87 #else
88 int ColorBoxX = 0;
89 int ColorBoxY = 0;
90 #endif
91 
92 gint volTOhandle;
93 
94 char bQuit=0;
95 
96 ////////////////////////////////////////////////////////////////////////
97 //
98 //						Pixmaps for controls
99 //
100 ////////////////////////////////////////////////////////////////////////
101 
102 #include "record.xpm"
103 #include "stop.xpm"
104 #include "play.xpm"
105 #include "lila.xpm"
106 #include "pause.xpm"
107 #include "paused.xpm"
108 
109 
110 //////////////////////////////////
111 //
112 //	Waveform generation
113 //
114 /////////////////////////////////
115 
116 #define SAMPLE_RATE 11025
117 
118 #define MAX_HARMONICS 10
119 #define DEFAULT_HARMONICS 3
120 
121 #define BEAT_MAX 40
122 
123 int nHarmonics = DEFAULT_HARMONICS;
124 
125 int *WaveTable;
126 
127 double curval;
128 
129 double harmonic_curtimeL[MAX_HARMONICS];
130 double harmonic_curtimeR[MAX_HARMONICS];
131 
132 double curtime;
133 double curtime2;
134 
135 volatile double increment=300;
136 volatile double detune=10.0;
137 volatile double volume = 0.0;
138 volatile double phase = 0.0;
139 
140 //	Volume fade controls.
141 char Starting=1;
142 double VolumeTarget=50.0;
143 double VolumeDelta=0.5;
144 char Stopping=0;
145 
146 /* sequencer variables */
147 volatile char playing=0;
148 char paused=0;
149 char *playname = NULL;
150 FILE *fSequence=NULL;
151 char szInstruction[1024];
152 volatile int EndSeconds=0;	/* number of seconds when the current instruction expires */
153 double target;
154 double dBeatIncrement;
155 int LastSeconds;
156 
157 int count=0;
158 volatile int seconds=0;
159 char tmptime[7] = "00:00";
160 
161 // functions
162 gint volTimeOut(gpointer data);
163 
164 
165 
PrintHandler(const char * line)166 void PrintHandler(const char *line)
167 {
168 
169 }
170 
171 
Quit(GtkWidget * widget,gpointer data)172 void Quit (GtkWidget *widget, gpointer data)
173 {
174 
175 	if(Stopping) {
176 		bQuit=1;
177 		exit(0);
178 	}
179 
180 	Stopping=1;
181 	volTOhandle = gtk_timeout_add(10,volTimeOut,NULL);
182 //	bQuit=1;
183 }
184 
InitSequencer(const char * fname)185 int InitSequencer(const char *fname)
186 {
187 	fSequence = fopen(fname,"r");
188 	if(fSequence) {
189 		seconds=0;	/* so that the nonexistant current instruction is expired */
190 		gtk_widget_set_sensitive(GTK_WIDGET(scale_beat),FALSE);
191 		gtk_pixmap_set( GTK_PIXMAP(PlayPixWid), PausePix, PauseBit);
192 		playing=1;
193 		return(1);
194 	}
195 
196 	return(0);
197 }
198 
file_ok_sel(GtkWidget * w,GtkFileSelection * fs)199 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
200 {
201 	InitSequencer(gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
202 
203 
204 #ifdef DEBUG
205 	g_print ("Now playing %s\n",gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
206 #endif
207 
208 	gtk_object_destroy(GTK_OBJECT(fs));
209 
210 }
211 
SetPause(void)212 void SetPause(void)
213 {
214 
215 	if(paused)
216 		gtk_pixmap_set( GTK_PIXMAP(PlayPixWid), PausedPix, PausedBit);
217 	else
218 		gtk_pixmap_set( GTK_PIXMAP(PlayPixWid), PausePix, PauseBit);
219 }
220 
Play(GtkWidget * widget,gpointer data)221 void Play (GtkWidget *widget, gpointer data)
222 {
223 	GtkWidget *filew;
224 
225 	if(playing) {
226 		paused = 1- paused;
227 		SetPause();
228 		return;
229 	}
230 
231 	/* Create a new file selection widget */
232 	filew = gtk_file_selection_new ("File selection");
233 
234 	gtk_file_selection_hide_fileop_buttons( GTK_FILE_SELECTION(filew));
235 
236 	/* Connect the ok_button to file_ok_sel function */
237 	gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
238                              "clicked", (GtkSignalFunc) file_ok_sel, filew );
239 
240 	/* Connect the cancel_button to destroy the widget */
241 	gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
242                                     (filew)->cancel_button),
243                                     "clicked", (GtkSignalFunc) gtk_widget_destroy,
244                                     GTK_OBJECT (filew));
245 
246 	/* Lets set the filename, as if this were a save dialog, and we are giving
247 	a default filename */
248 	gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew),
249 										"~/.autozen/*.seq");
250 
251 	gtk_file_selection_complete( GTK_FILE_SELECTION(filew), "~/.autozen/*.seq");
252 	gtk_widget_show(filew);
253 }
254 
255 
CheckSequencer()256 void CheckSequencer()
257 {
258 char *token;
259 int tmp;
260 
261 #ifdef DEBUG
262 	printf("CheckSequencer: seconds = %u, EndSeconds = %u,increment = %d\n",seconds,EndSeconds,dBeatIncrement);
263 #endif
264 
265 	if(seconds >= EndSeconds) {	/* if instruction is expired */
266 		if(target) {
267 			detune = target;
268 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_beat), (BEAT_MAX - detune));
269 			target=0;
270 			dBeatIncrement = 0;
271 		}
272 
273 		fgets(szInstruction,sizeof(szInstruction),fSequence);	// fetch it in
274 #ifdef DEBUG
275 	printf("CheckSequencer: %s\n",szInstruction);
276 #endif
277 		token = strtok(szInstruction," ,\n");
278 
279 		if(!strcmp(token,"SET")) {
280 			/* we are to set the frequency */
281 			token = strtok(NULL," ,\n");
282 			/* token is the frequency */
283 			detune = atof(token);
284 #ifdef DEBUG
285 	printf("CheckSequencer: SET %d\n",detune);
286 #endif
287 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_beat), (BEAT_MAX - detune));
288 			target = seconds = EndSeconds = 0;
289 			return;
290 		}
291 
292 		if(!strcmp(token,"VOLUME")) {
293 			token = strtok(NULL," ,\n");
294 			/* token is the volume */
295 			VolumeTarget = atof(token);
296 #ifdef DEBUG
297 	printf("CheckSequencer: VOLUME %d\n",VolumeTarget);
298 #endif
299 			if(Starting)
300 				gtk_timeout_remove( volTOhandle);
301 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), (100 - VolumeTarget));
302 			return;
303 		}
304 
305 		if(!strcmp(token,"FADE")) {
306 			token = strtok(NULL," ,\n");
307 			/* token is the volume */
308 			VolumeTarget = atof(token);
309 			token = strtok(NULL," ,\n");
310 			/* token is the duration of the fade */
311 			Starting = atoi(token);
312 #ifdef DEBUG
313 	printf("CheckSequencer: FADE %f %u\n",VolumeTarget,Starting);
314 #endif
315 			VolumeDelta = ((VolumeTarget - volume) / Starting) /50;
316 			volTOhandle = gtk_timeout_add(10,volTimeOut,NULL);
317 			return;
318 		}
319 
320 		if(!strcmp(token,"BASE")) {
321 			/* we are to set the frequency */
322 			token = strtok(NULL," ,\n");
323 			/* token is the frequency */
324 			increment = atof(token);
325 #ifdef DEBUG
326 	printf("CheckSequencer: SET %d\n",detune);
327 #endif
328 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_base), (1000 - increment));
329 			return;
330 		}
331 
332 		if(!strcmp(token,"HARMONICS")) {
333 			/* we are to set the number of harmonics */
334 			token = strtok(NULL," ,\n");
335 			tmp = atoi(token);
336 			if(tmp < MAX_HARMONICS)
337 				nHarmonics = tmp;
338 
339 #ifdef DEBUG
340 	printf("CheckSequencer: HARMONICS %u\n",nHarmonics);
341 #endif
342 			return;
343 		}
344 
345 		if(!strcmp(token,"SLIDE")) {
346 			token = strtok(NULL," ,\n");
347 			target = atof(token);
348 			token = strtok(NULL," ,\n");
349 			EndSeconds = atof(token);
350 			dBeatIncrement = target - detune;
351 			dBeatIncrement/= EndSeconds;
352 			seconds = LastSeconds = 0;
353 			return;
354 		}
355 
356 		if(!strcmp(token,"HOLD")) {
357 			token = strtok(NULL," ,\n");
358 			target = detune;
359 			EndSeconds = atof(token);
360 			dBeatIncrement = 0;
361 			seconds = LastSeconds = 0;
362 			return;
363 		}
364 
365 		if(!strcmp(token,"PAUSE")) {
366 			paused = 1;
367 			SetPause();
368 			return;
369 		}
370 
371 		if(!strcmp(token,"EXIT")) {
372 			Quit(NULL,NULL);
373 			StopSequencer();
374 			return;
375 		}
376 
377 		if(!strcmp(token,"END")) {
378 			StopSequencer();
379 			return;
380 		}
381 	}	/* end if seconds >= EndSeconds */
382 
383 	if(paused) {
384 		EndSeconds++;	// delay the end!
385 		return;
386 	}	/* end if paused */
387 
388 	detune += dBeatIncrement;
389 	gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_beat), (BEAT_MAX - detune));
390 	return;
391 }	/* end CheckSequencer */
392 
393 
StopSequencer(void)394 int StopSequencer(void)
395 {
396 
397 	if(!playing)
398 		return(0);
399 
400 	playing=0;
401 	seconds = LastSeconds = 0;
402 
403 	target = dBeatIncrement = playing = paused = LastSeconds = seconds = EndSeconds = 0;
404 
405 	gtk_widget_set_sensitive(GTK_WIDGET(scale_beat),TRUE);
406 	gtk_pixmap_set( GTK_PIXMAP(PlayPixWid), PlayPix, PlayBit);
407 
408 	fclose(fSequence);
409 	fSequence = NULL;
410 	return(1);
411 }
412 
413 
414 
415 
416 
InitWaveTable(unsigned int SampleRate)417 int InitWaveTable(unsigned int SampleRate)
418 {
419 unsigned int i;
420 double increment = (2*M_PI) / SampleRate;
421 double Current=0;
422 
423 	WaveTable = (int *) calloc(SampleRate*2,sizeof(int));
424 
425 	for(i=0;i<SampleRate;i++,Current += increment) {
426 		WaveTable[i]= (int) floor( sin(Current) * 127);
427 	}
428 
429 	return(1);
430 }	// end InitWaveTable
431 
SoundBytesWritten(int audio_fd)432 int SoundBytesWritten(int audio_fd)
433 {
434 count_info info;
435 
436 	ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info);
437 
438 	return(info.bytes);
439 }
440 
SetStereo(int dsp,char Stereo)441 int SetStereo(int dsp,char Stereo)
442 {
443 int stereo = Stereo;     /* 0=mono, 1=stereo */
444 
445 	if (ioctl(dsp, SNDCTL_DSP_STEREO, &stereo)==-1) { /* Fatal error */
446 		perror("SNDCTL_DSP_STEREO");
447 		return(0);
448 	}
449 
450 	if (stereo != 1) {
451 		printf("\aNo sterio support\n");
452 		printf("Stereo support is REQUIRED for this to work!\n");
453 		return(0);
454 		// The device doesn't support stereo mode.
455 	}
456 
457 	return(1);
458 }
459 
460 
SetSampleRate(int audio_fd,unsigned int rate)461 unsigned int SetSampleRate(int audio_fd, unsigned int rate)
462 {
463 unsigned int SampleRate = rate;
464 
465 	if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &SampleRate)==-1) { /* Fatal error */
466 		perror("SNDCTL_DSP_SPEED");
467 		return(FALSE);
468 	}
469 
470 	return(SampleRate);	// this is the actual sample rate which SHOULD be near the input value!
471 }	// end SetSampleRate
472 
473 
value_change_no_invert(GtkWidget * widget,gpointer data)474 void value_change_no_invert(GtkWidget *widget, gpointer data)
475 {
476 	*((double *)data) = GTK_ADJUSTMENT(widget) ->value;
477 
478 #ifdef DEBUG
479     g_print ("Value Change: %f\n",*((double *)data));
480 #endif
481 }
482 
value_change(GtkWidget * widget,gpointer data)483 void value_change(GtkWidget *widget, gpointer data)
484 {
485 	*((double *)data) = GTK_ADJUSTMENT(widget) ->upper;
486 	*((double *)data) -= GTK_ADJUSTMENT(widget) ->value;
487 	if(!playing)
488 		seconds=0;
489 
490 #ifdef DEBUG
491     g_print ("Value Change: %f\n",*((double *)data));
492 #endif
493 }
494 
label_change_value(GtkWidget * widget,gpointer label)495 void label_change_value(GtkWidget *widget, gpointer label)
496 {
497 	double data;
498 	char tmp[10];
499 	char **tmp2;
500 
501 	data = GTK_ADJUSTMENT(widget)->upper;
502 	data -= GTK_ADJUSTMENT(widget)->value;
503 	sprintf(tmp,"%02.1f",data);
504 
505 	gtk_label_set(GTK_LABEL(label),tmp);
506 
507 #ifdef DEBUG
508     g_print ("Lable Value Change: %s\n",tmp);
509 #endif
510 }
511 
512 
513 
514 
delete_event(GtkWidget * widget,GdkEvent * event,gpointer data)515 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
516 {
517     g_print ("delete event occured\n");
518     /* if you return FALSE in the "delete_event" signal handler,
519      * GTK will emit the "destroy" signal.  Returning TRUE means
520      * you don't want the window to be destroyed.
521      * This is useful for popping up 'are you sure you want to quit ?'
522      * type dialogs. */
523 
524     /* Change TRUE to FALSE and the main window will be destroyed with
525      * a "delete_event". */
526 
527     return (TRUE);
528 }
529 
ColorBoxDestroy(GtkWidget * widget,gpointer data)530 void ColorBoxDestroy(GtkWidget *widget, gpointer data)
531 {
532 
533 	gtk_timeout_remove( ColorBoxTOhandle );
534 }
535 
536 /* another callback */
destroy(GtkWidget * widget,gpointer data)537 void destroy (GtkWidget *widget, gpointer data)
538 {
539     gtk_main_quit ();
540 }
541 
IncrementCurtimes(double timeval[],int harmonics,double increment,double detune)542 void IncrementCurtimes(double timeval[], int harmonics, double increment, double detune)
543 {
544 	int i;
545 
546 	for(i=0;i<harmonics; i++) {
547 		timeval[i] += increment * pow(2,i) + detune;
548 		timeval[i] = fmod(timeval[i],SAMPLE_RATE);
549 	}
550 }
551 
ComputeSummation(double timeval[],int harmonics,double Volume)552 int ComputeSummation(double timeval[], int harmonics, double Volume)
553 {
554 	int i;
555 	int sigma=0;
556 
557 	for(i=0; i<harmonics; i++) {
558 		sigma += (int) (WaveTable[ (int) floor(timeval[i])] /(1<<i));
559 	}
560 
561 	sigma /=2;
562 
563 	sigma +=128;
564 
565 	return( floor( (Volume*sigma)/100));
566 }
567 
SetColorBox(double phase)568 void SetColorBox(double phase)
569 {
570 
571 	ColorBox_new_color.red = floor(0xffff * phase);
572 	ColorBox_new_color.green = floor(0xffff * (1-phase));
573 	ColorBox_new_color.blue = 0x0;
574 
575 	ColorBox_default_style = gtk_widget_get_style( GTK_WIDGET(ColorBox));
576 
577 	ColorBox_new_style = gtk_style_copy(ColorBox_default_style);
578 	ColorBox_new_style->bg[GTK_STATE_INSENSITIVE] = ColorBox_new_color;
579 	ColorBox_new_style->fg[GTK_STATE_INSENSITIVE] = ColorBox_new_color;
580 
581 	gtk_widget_set_style(GTK_WIDGET(ColorBox), ColorBox_new_style);
582 
583 	gtk_widget_queue_draw(GTK_WIDGET(ColorBox));
584 
585 // fprintf(stderr, "SetColorBox %f\n", phase);
586 }
587 
588 
PhaseDifference(double CurtimeL[],double CurtimeR[])589 double PhaseDifference(double CurtimeL[], double CurtimeR[])
590 {
591 	double a = CurtimeL[0];
592 	double b = CurtimeR[0];
593 	double res1, res2;
594 
595 
596 	a = fmod(a + SAMPLE_RATE + phase * SAMPLE_RATE, SAMPLE_RATE);
597 	if(a<b) {
598 		res1 = b-a;
599 		res2 = (a+SAMPLE_RATE)-b;
600 	} else {
601 		res1 = a-b;
602 		res2 = (b+SAMPLE_RATE)-a;
603 	}
604 
605 	if(res1<res2)
606 		return(res1 / SAMPLE_RATE);
607 
608 	return(res2 / SAMPLE_RATE);
609 }
610 
ColorBoxTimeOut(gpointer data)611 gint ColorBoxTimeOut(gpointer data) {
612 
613 //	SetColorBox( fmod( 2 * PhaseDifference(harmonic_curtimeL, harmonic_curtimeR) +phase +1.0, 1.0));
614 	SetColorBox( 2 * PhaseDifference(harmonic_curtimeL, harmonic_curtimeR) );
615 	return(TRUE);
616 }
617 
618 
SoundThread(void * v)619 void *SoundThread(void *v)
620 {
621 	int dsp;
622 	int iCur;
623 	int iCur2;
624 	int iCharIn;
625 	unsigned int SampleRate;
626 	int arg;
627 	char quit=0;
628 	int i,j;
629 
630 
631 	dsp = open("/dev/dsp",O_WRONLY);
632 
633 	if(dsp <0)
634 		fprintf(stderr,"Failed to open the sound card.\n");
635 
636 	// EXPERIMENTAL, shrink the buffer to improve response time!
637 	arg = 0x00800004;
638 	ioctl(dsp,SNDCTL_DSP_SETFRAGMENT,&arg);	// 128 16byte chunks. about 1/8 sec
639 
640 	if(!SetStereo(dsp,1))
641 //		return((void *) -1);
642 		printf("no stereo, might as well quit\n");
643 
644 	SampleRate = SetSampleRate(dsp,SAMPLE_RATE);
645 
646 	if(!SampleRate) {
647 		fprintf(stderr,"ERROR:\aCannot set a sample rate\n");
648 		SampleRate=8000;
649 //		return(0);
650 	}
651 
652 	InitWaveTable(SampleRate);
653 
654 	curtime=curtime2=0;
655 
656 	while(!bQuit) {
657 		for(j=0;j<SAMPLE_RATE;j++) {
658 
659 			IncrementCurtimes(harmonic_curtimeL, nHarmonics, increment, 0.0);
660 			IncrementCurtimes(harmonic_curtimeR, nHarmonics, increment, detune);
661 
662 			iCur = ComputeSummation(harmonic_curtimeL, nHarmonics, volume);
663 			iCur2 = ComputeSummation(harmonic_curtimeR, nHarmonics, volume);
664 
665 			write(dsp,&iCur,1);	// left
666 			write(dsp,&iCur2,1);	// right!
667 
668 			count++;	// bump the sample counter!
669 		}
670 
671 		seconds++;
672 
673 	}	// end while
674 
675 return(NULL);
676 }
677 
volTimeOut(gpointer data)678 gint volTimeOut(gpointer data) {
679 
680 	if(Stopping) {
681 		gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), 100 - (volume-0.5));
682 		if(volume <= 0.0) {
683 			bQuit=1;
684 			exit(0);
685 		}
686 		return(1);
687 	}
688 
689 	if(Starting) {
690 		gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), 100 - (volume+VolumeDelta));
691 		if(abs(volume-VolumeTarget) <= abs(VolumeDelta)) {
692 			Starting=0;
693 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), 100 - VolumeTarget);
694 		}
695 	} else {
696 		gtk_timeout_remove( volTOhandle);
697 	}
698 
699 	return(1);
700 }
701 
TimeOut(gpointer data)702 gint TimeOut(gpointer data)
703 {
704 	struct tm *tmst;
705 	time_t tttime;
706 	char tod[10];
707 
708 	tttime = time(NULL);
709 	tmst = localtime(&tttime);
710 
711 	sprintf(tod,"%02u:%02u:%02u",tmst->tm_hour,tmst->tm_min,tmst->tm_sec);
712 
713 
714 	sprintf(tmptime,"%02u:%02u",seconds/60,seconds%60);
715 	gtk_label_set(GTK_LABEL(data),tmptime);
716 	gtk_label_set(GTK_LABEL(ClockTime),tod);
717 
718 	if(playing)
719 		CheckSequencer();
720 
721 	return(TRUE);
722 }
723 
724 
create_HelpWindow(const char * text)725 GtkWidget *create_HelpWindow (const char *text)
726 {
727 	GtkWidget *HelpWindow;
728 	GtkWidget *vbox1;
729 	GtkWidget *help_text;
730 	GtkWidget *HelpQuit;
731 
732 #if GTK_MAJOR_VERSION >= 2
733 	GtkTextIter help_text_iter;
734 	GtkTextBuffer *help_text_buf;
735 #endif
736 
737 	HelpWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
738 	gtk_object_set_data (GTK_OBJECT (HelpWindow), "HelpWindow", HelpWindow);
739 	gtk_window_set_title (GTK_WINDOW (HelpWindow), "AutoZen Help");
740 	gtk_window_position (GTK_WINDOW (HelpWindow), GTK_WIN_POS_CENTER);
741 	gtk_window_set_policy (GTK_WINDOW (HelpWindow), TRUE, TRUE, FALSE);
742 
743 	vbox1 = gtk_vbox_new (FALSE, 0);
744 	gtk_object_set_data (GTK_OBJECT (HelpWindow), "vbox1", vbox1);
745 	gtk_widget_show (vbox1);
746 	gtk_container_add (GTK_CONTAINER (HelpWindow), vbox1);
747 
748 #if GTK_MAJOR_VERSION >= 2
749 	help_text = gtk_text_view_new ();
750 	help_text_buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (help_text));
751 	gtk_text_buffer_get_iter_at_offset (help_text_buf, &help_text_iter, 0);
752 	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW (help_text), GTK_WRAP_WORD);
753 #else
754 	help_text = gtk_text_new (NULL, NULL);
755 	gtk_text_set_word_wrap( GTK_TEXT( help_text ), TRUE);
756 	gtk_text_set_line_wrap( GTK_TEXT( help_text ), TRUE);
757 #endif
758 
759 
760 	gtk_object_set_data (GTK_OBJECT (HelpWindow), "help_text", help_text);
761 	gtk_widget_show (help_text);
762 	gtk_box_pack_start (GTK_BOX (vbox1), help_text, TRUE, TRUE, 6);
763 //	gtk_widget_set_sensitive (help_text, FALSE);
764 	GTK_WIDGET_UNSET_FLAGS (help_text, GTK_CAN_FOCUS);
765 	gtk_widget_realize (help_text);
766 #if GTK_MAJOR_VERSION >= 2
767 	gtk_text_buffer_insert (help_text_buf, &help_text_iter, text, strlen(text));
768 #else
769 	gtk_text_insert (GTK_TEXT (help_text), NULL, NULL, NULL, text, strlen(text));
770 #endif
771 
772 	HelpQuit = gtk_button_new_with_label ("Close");
773 	gtk_object_set_data (GTK_OBJECT (HelpWindow), "HelpQuit", HelpQuit);
774 	gtk_widget_show (HelpQuit);
775 	gtk_box_pack_start (GTK_BOX (vbox1), HelpQuit, FALSE, FALSE, 0);
776 	gtk_signal_connect_object (GTK_OBJECT (HelpQuit), "clicked",
777 		GTK_SIGNAL_FUNC (gtk_widget_destroy),
778 		GTK_OBJECT (HelpWindow));
779 
780 	return HelpWindow;
781 }
782 
Help(GtkWidget * widget,gpointer data)783 void Help(GtkWidget *widget, gpointer data)
784 {
785     GtkWidget *window;
786 
787     window = create_HelpWindow("AutoZen is a program to alter your brain waves through sound in order to help you to reach an altered state of consciousness. Full details are available at http://www.linuxlabs.com/autozen.html");
788 
789 	gtk_widget_show(window);
790 }
791 
792 GtkWidget *FreqTime;
793 
CreateColorBox()794 GtkWidget *CreateColorBox()
795 {
796 	    ColorBox = gtk_button_new();
797 
798 		gtk_widget_set_usize( GTK_WIDGET(ColorBox), ColorBoxX,ColorBoxY);
799 
800 		ColorBox_default_style = gtk_widget_get_style( GTK_WIDGET(ColorBox));
801 
802 		ColorBox_new_style = gtk_style_copy(ColorBox_default_style);
803 		ColorBox_new_style->bg[GTK_STATE_NORMAL] = ColorBox_new_color;
804 		ColorBox_new_style->fg[GTK_STATE_NORMAL] = ColorBox_new_color;
805 
806 		gtk_widget_set_style(GTK_WIDGET(ColorBox), ColorBox_new_style);
807 
808 		gtk_widget_set_sensitive(GTK_WIDGET(ColorBox), FALSE);
809 
810 	    gtk_widget_show (ColorBox);
811 
812 		return(ColorBox);
813 }
814 
815 
CreateAutoZen(GtkWidget * window)816 GtkWidget *CreateAutoZen(GtkWidget *window)
817 {
818     /* GtkWidget is the storage type for widgets */
819 	GtkStyle  *wstyle;
820 
821 	GtkWidget *main_table;
822 
823     GtkWidget *button;
824 	GtkWidget *beat_label;
825 
826 	GtkWidget *base_label;
827 
828 	GtkWidget *scale_vol;
829 	GtkWidget *vol_label;
830 
831 	GtkWidget *lable;
832 	GtkWidget *ClockLable;
833 	GtkWidget *FreqLable;
834 	GtkWidget *ColorBoxPhaseLable;
835 
836 	GtkWidget *RecordBox;
837 
838 	GtkWidget *RecordButton;
839 	GtkWidget *RecPixWid;
840 	GdkPixmap *RecordPix;
841 	GdkBitmap *RecordBit;
842 
843 	GtkWidget *StopButton;
844 	GtkWidget *StopPixWid;
845 	GdkPixmap *StopPix;
846 	GdkBitmap *StopBit;
847 
848 	GtkWidget *PlayButton;
849 
850 	GtkWidget *LiLaPixWid;
851 	GdkPixmap *LiLaPix;
852 	GdkBitmap *LiLaBit;
853 
854 	GtkWidget *LiLaEvent;
855 
856 
857 	wstyle = gtk_widget_get_style(window);
858 
859 //	the control layout table
860 	main_table = gtk_table_new(9,6,FALSE);
861 
862 	gtk_table_set_col_spacing(GTK_TABLE(main_table), 0, 5);
863 	gtk_table_set_col_spacing(GTK_TABLE(main_table), 1, 5);
864 //	gtk_table_set_col_spacing(GTK_TABLE(main_table), 6, 5);
865 
866 //	app name
867 //	lable = gtk_label_new("Autozen 1.1");
868 //	gtk_table_attach_defaults(GTK_TABLE(main_table),lable,1,6,0,1);
869 //	gtk_widget_show (lable);
870 
871 	// LiLa Logo
872 	LiLaPix = gdk_pixmap_create_from_xpm_d( window->window,  &LiLaBit, &(wstyle->bg[GTK_STATE_NORMAL]), (gchar **) &lila );
873 
874 	LiLaPixWid = gtk_pixmap_new( LiLaPix, LiLaBit );
875 
876 	gtk_widget_show( LiLaPixWid );
877 
878 
879 	LiLaEvent = gtk_button_new();
880 	gtk_button_set_relief( GTK_BUTTON(LiLaEvent), GTK_RELIEF_NONE);
881 
882 
883 	gtk_widget_show( LiLaEvent );
884 
885 	gtk_container_add( GTK_CONTAINER(LiLaEvent), LiLaPixWid );
886 
887 	gtk_table_attach_defaults(GTK_TABLE(main_table), LiLaEvent,0,7,0,1);
888 
889     gtk_signal_connect (GTK_OBJECT (LiLaEvent), "clicked",
890                         GTK_SIGNAL_FUNC (Help), NULL);
891 
892 //	clock
893 	ClockTime = gtk_label_new("00:00:00");
894 	gtk_table_attach_defaults(GTK_TABLE(main_table),ClockTime,2,4,1,2);
895     gtk_widget_show (ClockTime);
896 
897 	ClockLable = gtk_label_new("Time");
898 	gtk_table_attach_defaults(GTK_TABLE(main_table),ClockLable,2,4,2,3);
899     gtk_widget_show (ClockLable);
900 
901 //	freqTime
902 	FreqTime = gtk_label_new("00:00:00");
903 	gtk_table_attach_defaults(GTK_TABLE(main_table),FreqTime,2,4,3,4);
904     gtk_widget_show (FreqTime);
905 
906 	FreqLable = gtk_label_new("Time in Freq");
907 	gtk_table_attach_defaults(GTK_TABLE(main_table),FreqLable,2,4,4,5);
908     gtk_widget_show (FreqLable);
909 
910 
911 ////////////////
912 //
913 //	The recorder controls
914 //
915 ///////////////
916 
917 	RecordBox = gtk_hbox_new(FALSE,0);
918 	wstyle = gtk_widget_get_style( window );
919 
920 	RecordPix = gdk_pixmap_create_from_xpm_d( window->window,  &RecordBit, &wstyle->bg[GTK_STATE_NORMAL], (gchar **) &xpm_record );
921 
922 	RecPixWid = gtk_pixmap_new( RecordPix, RecordBit );
923 	gtk_widget_show( RecPixWid );
924 	// record button
925 	RecordButton = gtk_button_new();
926 	gtk_container_add( GTK_CONTAINER(RecordButton), RecPixWid );
927 
928     gtk_widget_show (RecordButton);
929 	gtk_box_pack_start(GTK_BOX(RecordBox),RecordButton,FALSE,FALSE,0);
930 
931 // stop button
932 	StopPix = gdk_pixmap_create_from_xpm_d( window->window,  &StopBit, &wstyle->bg[GTK_STATE_NORMAL], (gchar **) &xpm_stop );
933 
934 	StopPixWid = gtk_pixmap_new( StopPix, StopBit );
935 	gtk_widget_show( StopPixWid );
936 	StopButton = gtk_button_new();
937     gtk_signal_connect (GTK_OBJECT (StopButton), "clicked",
938                         GTK_SIGNAL_FUNC (StopSequencer), NULL);
939 
940 	gtk_container_add( GTK_CONTAINER(StopButton), StopPixWid );
941     gtk_widget_show (StopButton);
942 
943 	gtk_box_pack_start(GTK_BOX(RecordBox),StopButton,FALSE,FALSE,0);
944 
945 // play button
946 	PlayPix = gdk_pixmap_create_from_xpm_d( window->window,  &PlayBit, &wstyle->bg[GTK_STATE_NORMAL], (gchar **) &xpm_play );
947 
948 	PlayPixWid = gtk_pixmap_new( PlayPix, PlayBit );
949 	gtk_widget_show( PlayPixWid );
950 	PlayButton = gtk_button_new();
951 
952     gtk_signal_connect (GTK_OBJECT (PlayButton), "clicked",
953                         GTK_SIGNAL_FUNC (Play), NULL);
954 
955 	gtk_container_add( GTK_CONTAINER(PlayButton), PlayPixWid );
956     gtk_widget_show (PlayButton);
957 	gtk_box_pack_start(GTK_BOX(RecordBox),PlayButton,FALSE,FALSE,0);
958 
959 	gtk_table_attach_defaults(GTK_TABLE(main_table),RecordBox,2,4,5,6);
960     gtk_widget_show (RecordBox);
961 
962 // Pause widget for play button
963 	PausePix = gdk_pixmap_create_from_xpm_d( window->window,  &PauseBit, &wstyle->bg[GTK_STATE_NORMAL], (gchar **) &xpm_pause );
964 	PausedPix = gdk_pixmap_create_from_xpm_d( window->window,  &PausedBit, &wstyle->bg[GTK_STATE_NORMAL], (gchar **) &xpm_paused );
965 
966 
967 //	the Quit button
968 
969     button = gtk_button_new_with_label ("Quit");
970 
971     gtk_signal_connect (GTK_OBJECT (button), "clicked",
972                         GTK_SIGNAL_FUNC (Quit), NULL);
973 
974 	gtk_table_attach_defaults(GTK_TABLE(main_table),button,2,4,6,7);
975 
976     gtk_widget_show (button);
977 
978 //	set up beat slider
979 
980 	BeatFreq  = gtk_label_new("10.0");
981 	gtk_table_attach_defaults(GTK_TABLE(main_table),BeatFreq,0,1,1,2);
982     gtk_widget_show (BeatFreq);
983 
984 	adj_beat = gtk_adjustment_new(BEAT_MAX - 10,0,BEAT_MAX,0.1,0.1,0);
985     gtk_signal_connect (GTK_OBJECT (adj_beat), "value_changed",
986                         GTK_SIGNAL_FUNC (value_change), (gpointer) &detune);
987 
988     gtk_signal_connect (GTK_OBJECT (adj_beat), "value_changed",
989                         GTK_SIGNAL_FUNC (label_change_value), BeatFreq);
990 
991 	scale_beat = gtk_vscale_new(GTK_ADJUSTMENT(adj_beat));
992 	gtk_scale_set_draw_value( GTK_SCALE(scale_beat), FALSE);
993 	gtk_table_attach_defaults(GTK_TABLE(main_table),scale_beat,0,1,2,6);
994 
995     gtk_widget_show (scale_beat);
996 	beat_label = gtk_label_new("Beat");
997 	gtk_table_attach_defaults(GTK_TABLE(main_table),beat_label,0,1,6,7);
998     gtk_widget_show (beat_label);
999 
1000 //	set up base slider
1001 	BaseFreq = gtk_label_new("300.0");
1002 	gtk_table_attach_defaults(GTK_TABLE(main_table),BaseFreq,1,2,1,2);
1003     gtk_widget_show (BaseFreq);
1004 
1005 	adj_base = gtk_adjustment_new(700,50,1000,1,10,0);
1006     gtk_signal_connect (GTK_OBJECT (adj_base), "value_changed",
1007                         GTK_SIGNAL_FUNC (value_change), (gpointer) &increment);
1008 
1009     gtk_signal_connect (GTK_OBJECT (adj_base), "value_changed",
1010                         GTK_SIGNAL_FUNC (label_change_value), BaseFreq);
1011 
1012 	scale_base = gtk_vscale_new(GTK_ADJUSTMENT(adj_base));
1013 	gtk_scale_set_draw_value( GTK_SCALE(scale_base), FALSE);
1014 	gtk_table_attach_defaults(GTK_TABLE(main_table),scale_base,1,2,2,6);
1015     gtk_widget_show (scale_base);
1016 	base_label = gtk_label_new("Base");
1017 	gtk_table_attach_defaults(GTK_TABLE(main_table),base_label,1,2,6,7);
1018     gtk_widget_show (base_label);
1019 
1020 //	set up volume slider
1021 	VolLabel = gtk_label_new("50.0");
1022 	gtk_table_attach_defaults(GTK_TABLE(main_table),VolLabel,5,6,1,2);
1023     gtk_widget_show (VolLabel);
1024 	adj_vol = gtk_adjustment_new(100-volume,0,100,1,10,0);
1025     gtk_signal_connect (GTK_OBJECT (adj_vol), "value_changed",
1026                         GTK_SIGNAL_FUNC (value_change), (gpointer) &volume);
1027 
1028     gtk_signal_connect (GTK_OBJECT (adj_vol), "value_changed",
1029                         GTK_SIGNAL_FUNC (label_change_value), VolLabel);
1030 
1031 	scale_vol = gtk_vscale_new(GTK_ADJUSTMENT(adj_vol));
1032 	gtk_scale_set_draw_value( GTK_SCALE(scale_vol), FALSE);
1033 	gtk_table_attach_defaults(GTK_TABLE(main_table),scale_vol,5,6,2,6);
1034 //    gtk_container_add (GTK_CONTAINER (window), scale_vol);
1035     gtk_widget_show (scale_vol);
1036 	vol_label = gtk_label_new("Vol");
1037 	gtk_table_attach_defaults(GTK_TABLE(main_table),vol_label,5,6,6,7);
1038     gtk_widget_show (vol_label);
1039 
1040     /* and the window */
1041 
1042 //	the ColorBox button
1043 	if(ColorBoxX && ColorBoxY) {
1044 //		PhaseLabel = gtk_label_new("50.0");
1045 //		gtk_table_attach_defaults(GTK_TABLE(main_table),VolLabel,5,6,1,2);
1046 //	    gtk_widget_show (VolLabel);
1047 		adj_colorboxphase = gtk_adjustment_new(0,-0.5,0.5,0.01,0.1,0);
1048 	    gtk_signal_connect (GTK_OBJECT (adj_colorboxphase), "value_changed",
1049 	                        GTK_SIGNAL_FUNC (value_change_no_invert), (gpointer) &phase);
1050 
1051 //	    gtk_signal_connect (GTK_OBJECT (adj_vol), "value_changed",
1052 //	                        GTK_SIGNAL_FUNC (label_change_value), VolLabel);
1053 
1054 		scale_colorboxphase = gtk_hscale_new(GTK_ADJUSTMENT(adj_colorboxphase));
1055 //		gtk_scale_set_draw_value( GTK_SCALE(scale_colorboxphase), FALSE);
1056 		gtk_scale_set_digits( GTK_SCALE(scale_colorboxphase), 2);
1057 		gtk_table_attach_defaults(GTK_TABLE(main_table),scale_colorboxphase,0,6,7,8);
1058 	    gtk_widget_show (scale_colorboxphase);
1059 //		vol_label = gtk_label_new("Vol");
1060 //		gtk_table_attach_defaults(GTK_TABLE(main_table),vol_label,5,6,6,7);
1061 //	    gtk_widget_show (vol_label);
1062 	}
1063 
1064 
1065     gtk_widget_show (main_table);
1066 
1067 	return(main_table);
1068 }
1069 
SetupSequenceDirs(void)1070 void SetupSequenceDirs(void)
1071 {
1072 	struct stat st;
1073 	int res;
1074 	char fname[500];
1075 
1076 	sprintf(fname,"%s/.autozen",getenv("HOME"));
1077 
1078 	res = stat(fname,&st);
1079 	if(res<0) {
1080 		mkdir(fname,0700);
1081 		strcat(fname,"/public.seq");
1082 		symlink(PUBLIC_SEQUENCES, fname);
1083 	}
1084 }
1085 
1086 
main(int argc,char * argv[])1087 int main (int argc, char *argv[])
1088 {
1089     GtkWidget *window;
1090     GtkWidget *CBwindow;
1091 	pthread_t stp;
1092 	int	next_arg=1;
1093 
1094     gtk_init (&argc, &argv);
1095 
1096 
1097 	while(next_arg < argc && argv[next_arg][0] == '-') {
1098 
1099 		if(!strcasecmp(argv[next_arg], "-colorbox")) {
1100 			next_arg++;
1101 			if(argc>next_arg && atoi(argv[next_arg])) {
1102 				ColorBoxX = atoi(argv[next_arg++]);
1103 				ColorBoxY = atoi(argv[next_arg++]);
1104 			} else {
1105 				ColorBoxX = COLORBOX_X;
1106 				ColorBoxY = COLORBOX_Y;
1107 			}
1108 		} else if(!strcasecmp(argv[next_arg], "-harmonics")) {
1109 			next_arg++;
1110 			if(argc>next_arg && atoi(argv[next_arg]))
1111 				nHarmonics = atoi(argv[next_arg++]);
1112 				if(nHarmonics > MAX_HARMONICS)
1113 					nHarmonics = MAX_HARMONICS;
1114 		} else if(!strcasecmp(argv[next_arg], "-help") || !strcasecmp(argv[next_arg], "-h")) {
1115 			printf("%s [-colorbox [<x> <y>]] [-harmonics <n>] [<sequence>]\n",argv[0]);
1116 			exit(0);
1117 		}
1118 
1119 
1120 	}
1121 
1122 	SetupSequenceDirs();
1123 
1124     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1125 
1126 	gtk_window_set_wmclass( GTK_WINDOW(window), "autozen", "AutoZen");
1127 
1128     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1129                         GTK_SIGNAL_FUNC (delete_event), NULL);
1130 
1131     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1132                         GTK_SIGNAL_FUNC (destroy), NULL);
1133 
1134     /* sets the border width of the window. */
1135     gtk_container_border_width (GTK_CONTAINER (window), 10);
1136 
1137 	gtk_window_set_title( GTK_WINDOW(window), "AutoZen 2.1");
1138 
1139 	gtk_window_set_position( GTK_WINDOW(window) ,GTK_WIN_POS_CENTER);
1140 
1141     gtk_widget_show (window);
1142 
1143     gtk_container_add (GTK_CONTAINER (window), CreateAutoZen(window));
1144 
1145 	if(ColorBoxX && ColorBoxY) {
1146     	CBwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1147     	gtk_signal_connect (GTK_OBJECT (CBwindow), "destroy",
1148                         GTK_SIGNAL_FUNC (ColorBoxDestroy), NULL);
1149 
1150     	gtk_widget_show (CBwindow);
1151     	gtk_container_add (GTK_CONTAINER (CBwindow), CreateColorBox());
1152 	}
1153 
1154 	///////////////////////////////////////////
1155 	//
1156 	//	GUI setup done, now check args for a sequence to play
1157 	//
1158 	//////////////////////////////////////////
1159 
1160 	pthread_create(&stp,NULL,SoundThread,NULL);
1161 	gtk_timeout_add(1000,TimeOut,FreqTime);
1162 	volTOhandle = gtk_timeout_add(10,volTimeOut,FreqTime);
1163 
1164 	if(ColorBoxX && ColorBoxY)
1165 		ColorBoxTOhandle = gtk_timeout_add(10,ColorBoxTimeOut,FreqTime);
1166 
1167 	if(argc >next_arg) {
1168 		InitSequencer(argv[next_arg]);
1169 		CheckSequencer();
1170 	}
1171 
1172 	///////////////////	Main Loop ///////////////
1173     gtk_main ();
1174 
1175     return 0;
1176 }
1177 
1178