libxputty 0.1
Loading...
Searching...
No Matches
xtuner_private.c
Go to the documentation of this file.
1/*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2019 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21
22#include "xtuner_private.h"
23
24
25static const char *note_sharp[] = {"A","A#","B","C","C#","D","D#","E","F","F#","G","G#"};
26static const char *note_fr[] = {"La","La#","Si","Do","Do#","Ré","Ré#","Mi","Fa","Fa#","Sol","Sol#"};
27static const char *note_flat[] = {"A","Bb","B","C","Db","D","Eb","E","F","Gb","G","Ab"};
28static const char *note_fr_flat[] = {"La","La♭","Si","Do","Do♭","Ré","Ré♭","Mi","Fa","Fa♭","Sol","Sol♭"};
29static const char* note_19[19] = {"A","A♯","B♭","B","B♯","C","C♯","D♭","D","D♯","E♭","E","E♯","F","F♯","G♭","G","G♯","A♭"};
30static const char* note_fr_19[19] = {"La","La♯","Si♭","Si","Si♯","Do","Do♯","Ré♭","Ré","Ré♯","Mi♭","Mi","Mi♯","Fa","Fa♯","Sol♭","Sol","Sol♯","La♭"};
31static const char* note_24[24] = {"A","A¼♯","A♯","A¾♯","B","B¼♯","C","C¼♯","C♯","C¾♯","D","D¼♯","D♯","D¾♯","E","E¼♯","F","F¼♯","F♯","F¾♯","G","G¼♯","G♯","G¾♯"};
32static const char* note_fr_24[24] = {"La","La¼♯","La♯","La¾♯","Si","Si¼♯","Do","Do¼♯","Do♯","Do¾♯","Ré","Ré¼♯","Ré♯","Ré¾♯","Mi","E¼♯","Fa","Fa¼♯","Fa♯","Fa¾♯","Sol","Sol¼♯","Sol♯","Sol¾♯"};
33static const char* note_31[31] = {"A","B♭♭","A♯","B♭","A♯♯","B","C♭","B♯","C ","D♭♭","C♯","D♭","C♯♯","D","E♭♭","D♯","E♭","D♯♯","E","F♭","E♯","F","G♭♭","F♯","G♭","F♯♯","G","A♭♭","G♯","A♭","G♯♯"};
34static const char* note_fr_31[31] = {"La","Si♭♭","La♯","Si♭","La♯♯","Si","Do♭","Si♯","Do ","Ré♭♭","Do♯","Ré♭","Do♯♯","Ré","Mi♭♭","Ré♯","Mi♭","Ré♯♯","Mi","Fa♭","Mi♯","Fa","Sol♭♭","Fa♯","Sol♭","Fa♯♯","Sol","La♭♭","Sol♯","La♭","Sol♯♯"};
35static const char* note_53[53] = {"la","laa","lo","law","ta","teh","te","tu","tuh","ti","tih","to","taw","da","do","di","daw","ro","rih","ra","ru","ruh","reh","re ","ri","raw","ma","meh","me","mu","muh","mi","maa","mo","maw","fe","fa","fih","fu","fuh","fi","se","suh","su","sih","sol","si","saw","lo","leh","le","lu","luh"};
36static const char *octave[] = {"0","1","2","3","4","5"," "};
37
38static void _tuner_triangle(Widget_t *w, float posx, float posy, float width, float height)
39{
40 float h2 = height/2.0;
41 cairo_move_to(w->crb, posx, posy-h2);
42 if (width > 0) {
43 cairo_curve_to(w->crb,posx, posy-h2, posx+10, posy, posx, posy+h2);
44 } else {
45 cairo_curve_to(w->crb,posx, posy-h2, posx-10, posy, posx, posy+h2);
46 }
47 cairo_curve_to(w->crb,posx, posy+h2, posx+width/2, posy+h2, posx+width, posy);
48 cairo_curve_to(w->crb, posx+width, posy, posx+width/2, posy-h2, posx, posy-h2);
49 cairo_fill(w->crb);
50 cairo_new_path (w->crb);
51}
52
53static int _get_tuner_temperament(Widget_t *w) {
54 XTuner *xt = (XTuner *)w->parent_struct;
55 if((int)xt->temperament == 0) return 12;
56 else if((int)xt->temperament == 1) return 19;
57 else if((int)xt->temperament == 2) return 24;
58 else if((int)xt->temperament == 3) return 31;
59 else if((int)xt->temperament == 4) return 53;
60 else return 12;
61}
62
63static const char **_get_note_set(Widget_t *w) {
64 XTuner *xt = (XTuner *)w->parent_struct;
65 if((int)xt->temperament == 0) {
66 if (xt->lang == 1) return note_fr;
67 return note_sharp;
68 } else if((int)xt->temperament == 1) {
69 if (xt->lang == 1) return note_fr_19;
70 return note_19;
71 } else if((int)xt->temperament == 2) {
72 if (xt->lang == 1) return note_fr_24;
73 return note_24;
74 } else if((int)xt->temperament == 3) {
75 if (xt->lang == 1) return note_fr_31;
76 return note_31;
77 } else if((int)xt->temperament == 4) return note_53;
78 else {
79 if (xt->lang == 1) return note_fr_flat;
80 return note_flat;
81 }
82
83}
84
85void _draw_tuner(void *w_, void* user_data) {
86 Widget_t *w = (Widget_t*)w_;
87 if (!w) return;
88 XTuner *xt = (XTuner *)w->parent_struct;
89 Metrics_t metrics;
90 os_get_window_metrics(w, &metrics);
91 int width = metrics.width;
92 int height = metrics.height;
93 if (!metrics.visible) return;
94 float x0 = width/2;
95 float y0 = height/2;
96
98 cairo_paint (w->crb);
99
100 cairo_pattern_t* pat = cairo_pattern_create_linear (0, 0,x0, 0);
101 cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT);
102 cairo_pattern_add_color_stop_rgb (pat, 1, 0.1, 0.8, 0.1);
103 cairo_pattern_add_color_stop_rgb (pat, 0.7, 0.8, 0.8, 0.1);
104 cairo_pattern_add_color_stop_rgb (pat, 0, 1, 0.1, 0.1);
105
106 cairo_set_source_rgb(w->crb,0.2,0.2,0.2);
107 int i = 0;
108 for (; i < width/20 +1; ++i) {
109 cairo_rectangle(w->crb,(width/2)+i*10, 5, 5, 20);
110 cairo_fill(w->crb);
111 }
112 for (; i >0; --i) {
113 cairo_rectangle(w->crb,(width/2)-i*10, 5, 5, 20);
114 cairo_fill(w->crb);
115 }
116
117
118 cairo_set_source_rgb(w->crb,0.2,0.2,0.2);
119 _tuner_triangle(w, width/5.8,y0 , 25/w->scale.ascale, 20/w->scale.ascale);
120 _tuner_triangle(w, width/1.2, y0, -25/w->scale.ascale, 20/w->scale.ascale);
121
122 float value = adj_get_value(w->adj);
123 float scale = -0.5;
124
125 float fvis = _get_tuner_temperament(w) * (log2f(value/xt->ref_freq) + 4);
126 float fvisr = round(fvis);
127 int vis = fvisr;
128 int indicate_oc = round((fvisr+xt->temp_adjust)/_get_tuner_temperament(w));
129 const int octsz = sizeof(octave) / sizeof(octave[0]);
130 if (indicate_oc < 0 || indicate_oc >= octsz) {
131 // just safety, should not happen with current parameters
132 // (pitch tracker output 23 .. 999 Hz)
133 indicate_oc = octsz - 1;
134 }
135
136 scale = (fvis-vis) / 4;
137 float cent = (scale * 10000) / 25;
138 vis = vis % _get_tuner_temperament(w);
139 if (vis < 0) {
140 vis += _get_tuner_temperament(w);
141 }
142
143 if (value > 24.0 && value < 999.0) {
144 if (scale < 0.004) {
145 cairo_set_source_rgb(w->crb,0.80,0.79,0.01);
146 _tuner_triangle(w, (width/5.8),y0 , 25/w->scale.ascale, 20/w->scale.ascale);
147 _tuner_triangle(w, (width/5.8)-(300*scale)/w->scale.ascale,y0 , 25/w->scale.ascale, 20/w->scale.ascale);
148 _tuner_triangle(w, (width/5.8)-(600*scale)/w->scale.ascale,y0 , 25/w->scale.ascale, 20/w->scale.ascale);
149 }
150 if (scale > -0.004) {
151 cairo_set_source_rgb(w->crb,0.80,0.79,0.01);
152 _tuner_triangle(w, (width/1.2), y0, -25/w->scale.ascale, 20/w->scale.ascale);
153 _tuner_triangle(w, (width/1.2)-(300*scale)/w->scale.ascale, y0, -25/w->scale.ascale, 20/w->scale.ascale);
154 _tuner_triangle(w, (width/1.2)-(600*scale)/w->scale.ascale, y0, -25/w->scale.ascale, 20/w->scale.ascale);
155 }
156 }
157 // display note
158 cairo_select_font_face (w->crb, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
159 cairo_set_source_rgba(w->crb, fabsf(scale)*2, 1-(scale*scale*4), 0.2,max(0,1-(fabsf(scale)*6)));
160 cairo_set_font_size(w->crb, (w->app->big_font*2)/w->scale.ascale);
161 cairo_text_extents_t extents;
162
163 if (value > 24.0 && value < 999.0) {
164 cairo_text_extents(w->crb,_get_note_set(w)[vis] , &extents);
165 float c = (extents.width/2)+10.0;
166 cairo_move_to(w->crb,x0-c , y0+10 );
167 cairo_show_text(w->crb, _get_note_set(w)[vis]);
168 cairo_set_font_size(w->crb, (w->app->small_font*2)/w->scale.ascale);
169 cairo_move_to(w->crb,x0+c-10.0, y0+10+ extents.height/2 );
170 cairo_show_text(w->crb, octave[indicate_oc]);
171
172 char s[64];
173 char sc[64];
174 snprintf(s, 63, "%.2f Hz", value);
176 cairo_set_font_size (w->crb, w->app->big_font/w->scale.ascale);
177 cairo_text_extents(w->crb,s , &extents);
178 cairo_move_to (w->crb, width/1.1-extents.width, height-extents.height );
179 cairo_show_text(w->crb, s);
180 snprintf(sc, 63, "%.2f cent", cent);
181 cairo_text_extents(w->crb,sc , &extents);
182 cairo_move_to (w->crb, width/4.1-extents.width, height-extents.height );
183 cairo_show_text(w->crb, sc);
184
185 cairo_set_source(w->crb,pat);
186 int m = 1000*scale;
187 int n = 100*scale;
188 int o = 500*scale;
189 int p = 250*scale;
190 //if (m==0 && xt->smove !=0) xt->move=width/20;
191 xt->smove = m;
192 xt->move +=m;
193 static int cmove = 0;
194 static int omove = 0;
195 static int pmove = 0;
196 cmove += n;
197 omove += o;
198 pmove += p;
199 if(xt->move<-width/20) xt->move=width/20;
200 else if(xt->move>width/20) xt->move=-width/20;
201 if(cmove<-width/20) cmove=width/20;
202 else if(cmove>width/20) cmove=-width/20;
203 if(omove<-width/20) omove=width/20;
204 else if(omove>width/20) omove=-width/20;
205 if(pmove<-width/20) pmove=width/20;
206 else if(pmove>width/20) pmove=-width/20;
207 if (m==0) {
208 if(xt->move<0) xt->move+=1;
209 else if(xt->move>0) xt->move-=1;
210 }
211 if (n==0) {
212 if(cmove<0) cmove+=1;
213 else if(cmove>0) cmove-=1;
214 }
215 if (o==0) {
216 if(omove<0) omove+=1;
217 else if(omove>0) omove-=1;
218 }
219 if (p==0) {
220 if(pmove<0) pmove+=1;
221 else if(pmove>0) pmove-=1;
222 }
223 for (int i = 0; i < 4; ++i) {
224 cairo_rectangle(w->crb,(width/2)-20 + (xt->move+i)*10, 5, 5, 5);
225 cairo_rectangle(w->crb,(width/2)-20 + (omove+i)*10, 10, 5, 5);
226 cairo_rectangle(w->crb,(width/2)-20 + (pmove+i)*10, 15, 5, 5);
227 cairo_rectangle(w->crb,(width/2)-20 + (cmove+i)*10, 20, 5, 5);
228 cairo_fill(w->crb);
229 }
230 } else {
231 cairo_set_source_rgb(w->crb,0.2,0.2,0.2);
232
233 cairo_set_font_size (w->crb, w->app->big_font/w->scale.ascale);
234 cairo_text_extents(w->crb, "000.00 Hz", &extents);
235 cairo_move_to (w->crb, width/1.1-extents.width, height-extents.height );
236 cairo_show_text(w->crb, "000.00 Hz");
237
238 cairo_text_extents(w->crb, "0.00 cent", &extents);
239 cairo_move_to (w->crb, width/4.1-extents.width, height-extents.height );
240 cairo_show_text(w->crb, "0.00 cent");
241
242 cairo_set_font_size(w->crb, (w->app->big_font*2)/w->scale.ascale);
243 cairo_text_extents(w->crb,"#" , &extents);
244 float c = (extents.width/2)+10.0;
245 cairo_move_to(w->crb,x0-c , y0+10 );
246 cairo_show_text(w->crb, "#");
247 cairo_set_font_size(w->crb, (w->app->small_font*2)/w->scale.ascale);
248 cairo_move_to(w->crb,x0+c-10.0, y0+10+ extents.height/2 );
249 cairo_show_text(w->crb, "0");
250 }
251 cairo_pattern_destroy(pat);
252}
Metrics_t - struct to receive window size, position & visibility Pass this struct to os_get_window_...
float ascale
Definition xwidget.h:369
Widget_t - struct to hold the basic Widget_t info.
Definition xwidget.h:457
Resize_t scale
Definition xwidget.h:525
Adjustment_t * adj
Definition xwidget.h:497
cairo_t * crb
Definition xwidget.h:489
void * parent_struct
Definition xwidget.h:473
Xputty * app
Definition xwidget.h:465
int temp_adjust
Definition xtuner.h:37
float ref_freq
Definition xtuner.h:34
int smove
Definition xtuner.h:39
int move
Definition xtuner.h:38
int big_font
Definition xputty.h:250
int small_font
Definition xputty.h:246
float adj_get_value(Adjustment_t *adj)
adj_get_value - get the current value of the Adjustment_t
void use_text_color_scheme(Widget_t *w, Color_state st)
use_text_color_scheme - use text Colors to paint on Widget_t
Definition xcolor.c:266
void use_bg_color_scheme(Widget_t *w, Color_state st)
use_bg_color_scheme - use background Colors to paint on Widget_t
Definition xcolor.c:252
@ NORMAL_
Definition xcolor.h:44
void _draw_tuner(void *w_, void *user_data)
_draw_tuner - draw the tuner on expose call
void os_get_window_metrics(Widget_t *w, Metrics_t *metrics)
os_get_window_metrics - Get the Merics_t struct related to a Widget_t