1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
37 #include "screen_access.h"
39 #include "statusbar.h"
41 #include "pitchscreen.h"
43 #define PITCH_MODE_ABSOLUTE 1
44 #define PITCH_MODE_SEMITONE -PITCH_MODE_ABSOLUTE
45 #define ICON_BORDER 12 /* icons are currently 7x8, so add ~2 pixels */
46 /* on both sides when drawing */
49 #define PITCH_MAX 2000
51 #define PITCH_SMALL_DELTA 1
52 #define PITCH_BIG_DELTA 10
53 #define PITCH_NUDGE_DELTA 20
56 static int pitch_mode
= PITCH_MODE_ABSOLUTE
; /* 1 - absolute, -1 - semitone */
66 static void pitchscreen_fix_viewports(struct viewport
*parent
,
67 struct viewport pitch_viewports
[PITCH_ITEM_COUNT
])
70 height
= font_get(parent
->font
)->height
;
71 for (n
= 0; n
< PITCH_ITEM_COUNT
; n
++)
73 pitch_viewports
[n
] = *parent
;
74 pitch_viewports
[n
].height
= height
;
76 pitch_viewports
[PITCH_TOP
].y
+= ICON_BORDER
;
78 pitch_viewports
[PITCH_MID
].x
+= ICON_BORDER
;
79 pitch_viewports
[PITCH_MID
].width
= parent
->width
- ICON_BORDER
*2;
80 pitch_viewports
[PITCH_MID
].height
= height
* 2;
81 pitch_viewports
[PITCH_MID
].y
+= parent
->height
/ 2 -
82 pitch_viewports
[PITCH_MID
].height
/ 2;
83 pitch_viewports
[PITCH_BOTTOM
].y
+= parent
->height
- height
- ICON_BORDER
;
86 /* must be called before pitchscreen_draw, or within
87 * since it neither clears nor updates the display */
88 static void pitchscreen_draw_icons (struct screen
*display
,
89 struct viewport
*parent
)
91 display
->set_viewport(parent
);
92 display
->mono_bitmap(bitmap_icons_7x8
[Icon_UpArrow
],
95 display
->mono_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
97 parent
->height
- 10, 7, 8);
98 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
100 parent
->height
/2 - 4, 7, 8);
101 display
->mono_bitmap(bitmap_icons_7x8
[Icon_FastBackward
],
103 parent
->height
/2 - 4, 7, 8);
106 static void pitchscreen_draw (struct screen
*display
, int max_lines
,
107 struct viewport pitch_viewports
[PITCH_ITEM_COUNT
], int pitch
)
110 unsigned char buf
[32];
112 bool show_lang_pitch
;
114 /* Hide "Pitch up/Pitch down" for a small screen */
118 display
->set_viewport(&pitch_viewports
[PITCH_TOP
]);
119 if (pitch_mode
== PITCH_MODE_ABSOLUTE
) {
120 ptr
= str(LANG_PITCH_UP
);
122 ptr
= str(LANG_PITCH_UP_SEMITONE
);
124 display
->getstringsize(ptr
,&w
,&h
);
125 display
->clear_viewport();
127 display
->putsxy((pitch_viewports
[PITCH_TOP
].width
/ 2) -
130 /* DOWN: Pitch Down */
131 display
->set_viewport(&pitch_viewports
[PITCH_BOTTOM
]);
132 if (pitch_mode
== PITCH_MODE_ABSOLUTE
) {
133 ptr
= str(LANG_PITCH_DOWN
);
135 ptr
= str(LANG_PITCH_DOWN_SEMITONE
);
137 display
->getstringsize(ptr
,&w
,&h
);
138 display
->clear_viewport();
140 display
->putsxy((pitch_viewports
[PITCH_BOTTOM
].width
/ 2) -
143 display
->set_viewport(&pitch_viewports
[PITCH_MID
]);
145 snprintf((char *)buf
, sizeof(buf
), "%s", str(LANG_PITCH
));
146 display
->getstringsize(buf
,&w
,&h
);
147 /* lets hide LANG_PITCH for smaller screens */
148 display
->clear_viewport();
149 if ((show_lang_pitch
= (max_lines
>= 3)))
150 display
->putsxy((pitch_viewports
[PITCH_MID
].width
/ 2) - (w
/ 2),
153 /* we don't need max_lines any more, reuse it*/
156 snprintf((char *)buf
, sizeof(buf
), "%d.%d%%",
157 pitch
/ 10, pitch
% 10 );
158 display
->getstringsize(buf
,&w
,&h
);
159 display
->putsxy((pitch_viewports
[PITCH_MID
].width
/ 2) - (w
/ 2),
160 (show_lang_pitch
? h
: h
/2), buf
);
162 /* What's wider? LANG_PITCH or the value?
163 * Only interesting if LANG_PITCH is actually drawn */
164 max_lines
= (show_lang_pitch
? ((max_lines
> w
) ? max_lines
: w
) : w
);
166 /* Let's treat '+' and '-' as equally wide
167 * This saves a getstringsize call
168 * Also, it wouldn't look nice if -2% shows up, but +2% not */
169 display
->getstringsize("+2%",&w
,&h
);
171 /* hide +2%/-2% for a narrow screens */
172 if (max_lines
< pitch_viewports
[PITCH_MID
].width
)
175 display
->putsxy(pitch_viewports
[PITCH_MID
].width
- w
, h
/2, "+2%");
177 display
->putsxy(0, h
/ 2, "-2%");
179 /* Lastly, a fullscreen update */
180 display
->set_viewport(NULL
);
184 static int pitch_increase(int pitch
, int delta
, bool allow_cutoff
)
189 if (pitch
+ delta
>= PITCH_MIN
) {
190 new_pitch
= pitch
+ delta
;
195 new_pitch
= PITCH_MIN
;
197 } else if (delta
> 0) {
198 if (pitch
+ delta
<= PITCH_MAX
) {
199 new_pitch
= pitch
+ delta
;
204 new_pitch
= PITCH_MAX
;
207 /* delta == 0 -> no real change */
210 sound_set_pitch(new_pitch
);
215 /* Factor for changing the pitch one half tone up.
216 The exact value is 2^(1/12) = 1.05946309436
217 But we use only integer arithmetics, so take
218 rounded factor multiplied by 10^5=100,000. This is
219 enough to get the same promille values as if we
220 had used floating point (checked with a spread
223 #define PITCH_SEMITONE_FACTOR 105946L
225 /* Some helpful constants. K is the scaling factor for SEMITONE.
226 N is for more accurate rounding
229 #define PITCH_K_FCT 100000UL
230 #define PITCH_N_FCT 10
231 #define PITCH_KN_FCT 1000000UL
233 static int pitch_increase_semitone(int pitch
, bool up
)
236 uint32_t round_fct
; /* How much to scale down at the end */
239 tmp
= tmp
* PITCH_SEMITONE_FACTOR
;
240 round_fct
= PITCH_K_FCT
;
242 tmp
= (tmp
* PITCH_KN_FCT
) / PITCH_SEMITONE_FACTOR
;
243 round_fct
= PITCH_N_FCT
;
245 /* Scaling down with rounding */
246 tmp
= (tmp
+ round_fct
/ 2) / round_fct
;
247 return pitch_increase(pitch
, tmp
- pitch
, false);
253 1 if USB was connected
256 int gui_syncpitchscreen_run(void)
259 int pitch
= sound_get_pitch();
260 int new_pitch
, delta
= 0;
264 struct viewport parent
[NB_SCREENS
]; /* should maybe
265 be a parameter of this function */
266 short max_lines
[NB_SCREENS
];
267 struct viewport pitch_viewports
[NB_SCREENS
][PITCH_ITEM_COUNT
];
269 /* initialize pitchscreen vps */
272 screens
[i
].clear_display();
273 viewport_set_defaults(&parent
[i
], i
);
274 max_lines
[i
] = viewport_get_nb_lines(&parent
[i
]);
275 pitchscreen_fix_viewports(&parent
[i
], pitch_viewports
[i
]);
277 /* also, draw the icons now, it's only needed once */
278 pitchscreen_draw_icons(&screens
[i
], &parent
[i
]);
280 #if CONFIG_CODEC == SWCODEC
281 pcmbuf_set_low_latency(true);
287 pitchscreen_draw(&screens
[i
], max_lines
[i
],
288 pitch_viewports
[i
], pitch
);
289 gui_syncstatusbar_draw(&statusbars
, true);
290 button
= get_action(CONTEXT_PITCHSCREEN
,HZ
);
292 case ACTION_PS_INC_SMALL
:
293 delta
= PITCH_SMALL_DELTA
;
296 case ACTION_PS_INC_BIG
:
297 delta
= PITCH_BIG_DELTA
;
300 case ACTION_PS_DEC_SMALL
:
301 delta
= -PITCH_SMALL_DELTA
;
304 case ACTION_PS_DEC_BIG
:
305 delta
= -PITCH_BIG_DELTA
;
308 case ACTION_PS_NUDGE_RIGHT
:
309 new_pitch
= pitch_increase(pitch
, PITCH_NUDGE_DELTA
, false);
310 nudged
= (new_pitch
!= pitch
);
314 case ACTION_PS_NUDGE_RIGHTOFF
:
316 pitch
= pitch_increase(pitch
, -PITCH_NUDGE_DELTA
, false);
321 case ACTION_PS_NUDGE_LEFT
:
322 new_pitch
= pitch_increase(pitch
, -PITCH_NUDGE_DELTA
, false);
323 nudged
= (new_pitch
!= pitch
);
327 case ACTION_PS_NUDGE_LEFTOFF
:
329 pitch
= pitch_increase(pitch
, PITCH_NUDGE_DELTA
, false);
334 case ACTION_PS_RESET
:
336 sound_set_pitch( pitch
);
339 case ACTION_PS_TOGGLE_MODE
:
340 pitch_mode
= -pitch_mode
;
348 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
354 if (pitch_mode
== PITCH_MODE_ABSOLUTE
) {
355 pitch
= pitch_increase(pitch
, delta
, true);
357 pitch
= pitch_increase_semitone(pitch
, delta
> 0 ? true:false);
363 #if CONFIG_CODEC == SWCODEC
364 pcmbuf_set_low_latency(false);