1 /* analogtv, Copyright (c) 2003-2018 Trevor Blackwell <tlb@tlb.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 #ifndef _XSCREENSAVER_ANALOGTV_H
13 #define _XSCREENSAVER_ANALOGTV_H
15 #include "thread_util.h"
18 #if defined(USE_IPHONE) || defined(HAVE_ANDROID)
23 You'll need these to generate standard NTSC TV signals
26 /* We don't handle interlace here */
29 ANALOGTV_VISLINES=200,
30 ANALOGTV_BOT=ANALOGTV_TOP + ANALOGTV_VISLINES,
32 /* This really defines our sampling rate, 4x the colorburst
33 frequency. Handily equal to the Apple II's dot clock.
34 You could also make a case for using 3x the colorburst freq,
35 but 4x isn't hard to deal with. */
38 /* Each line is 63500 nS long. The sync pulse is 4700 nS long, etc.
39 Define sync, back porch, colorburst, picture, and front porch
41 ANALOGTV_SYNC_START=0,
42 ANALOGTV_BP_START=4700*ANALOGTV_H/63500,
43 ANALOGTV_CB_START=5800*ANALOGTV_H/63500,
44 /* signal[row][ANALOGTV_PIC_START] is the first displayed pixel */
45 ANALOGTV_PIC_START=9400*ANALOGTV_H/63500,
46 ANALOGTV_PIC_LEN=52600*ANALOGTV_H/63500,
47 ANALOGTV_FP_START=62000*ANALOGTV_H/63500,
48 ANALOGTV_PIC_END=ANALOGTV_FP_START,
50 /* TVs scan past the edges of the picture tube, so normally you only
51 want to use about the middle 3/4 of the nominal scan line.
53 ANALOGTV_VIS_START=ANALOGTV_PIC_START + (ANALOGTV_PIC_LEN*1/8),
54 ANALOGTV_VIS_END=ANALOGTV_PIC_START + (ANALOGTV_PIC_LEN*7/8),
55 ANALOGTV_VIS_LEN=ANALOGTV_VIS_END-ANALOGTV_VIS_START,
57 ANALOGTV_HASHNOISE_LEN=6,
59 ANALOGTV_GHOSTFIR_LEN=4,
61 /* analogtv.signal is in IRE units, as defined below: */
62 ANALOGTV_WHITE_LEVEL=100,
63 ANALOGTV_GRAY50_LEVEL=55,
64 ANALOGTV_GRAY30_LEVEL=35,
65 ANALOGTV_BLACK_LEVEL=10,
66 ANALOGTV_BLANK_LEVEL=0,
67 ANALOGTV_SYNC_LEVEL=-40,
70 ANALOGTV_SIGNAL_LEN=ANALOGTV_V*ANALOGTV_H,
72 /* The number of intensity levels we deal with for gamma correction &c */
75 /* MAX_LINEHEIGHT corresponds to 2400 vertical pixels, beyond which
76 it interpolates extra black lines. */
77 ANALOGTV_MAX_LINEHEIGHT=12
81 typedef struct analogtv_input_s {
82 signed char signal[ANALOGTV_V+1][ANALOGTV_H];
87 void (*updater)(struct analogtv_input_s *inp);
89 double next_update_time;
93 typedef struct analogtv_font_s {
99 typedef struct analogtv_reception_s {
101 analogtv_input *input;
107 double ghostfir[ANALOGTV_GHOSTFIR_LEN];
108 double ghostfir2[ANALOGTV_GHOSTFIR_LEN];
113 } analogtv_reception;
116 The rest of this should be considered mostly opaque to the analogtv module.
119 struct analogtv_yiq_s {
121 } /*yiq[ANALOGTV_PIC_LEN+10] */;
123 typedef struct analogtv_s {
128 XWindowAttributes xgwa;
130 struct threadpool threads;
133 unsigned int onscreen_signature[ANALOGTV_V];
139 int interlace_counter;
143 /* If you change these, call analogtv_set_demod */
144 float tint_control,color_control,brightness_control,contrast_control;
145 float height_control, width_control, squish_control;
153 /* For fast display, set fakeit_top, fakeit_bot to
154 the scanlines (0..ANALOGTV_V) that can be preserved on screen.
155 fakeit_scroll is the number of scan lines to scroll it up,
156 or 0 to not scroll at all. It will DTRT if asked to scroll from
164 int use_cmap,use_color;
167 XShmSegmentInfo shm_info;
168 int visdepth,visclass,visbits;
169 int red_invprec, red_shift;
170 int green_invprec, green_shift;
171 int blue_invprec, blue_shift;
172 unsigned long red_mask, green_mask, blue_mask;
175 int usewidth,useheight,xrepl,subwidth;
176 XImage *image; /* usewidth * useheight */
178 int screen_xo,screen_yo; /* centers image in window */
180 int flutter_horiz_desync;
183 struct timeval last_display_time;
187 /* Add hash (in the radio sense, not the programming sense.) These
188 are the small white streaks that appear in quasi-regular patterns
189 all over the screen when someone is running the vacuum cleaner or
190 the blender. We also set shrinkpulse for one period which
191 squishes the image horizontally to simulate the temporary line
192 voltate drop when someone turns on a big motor */
193 double hashnoise_rpm;
194 int hashnoise_counter;
195 int hashnoise_times[ANALOGTV_V];
196 int hashnoise_signal[ANALOGTV_V];
198 int hashnoise_enable;
201 float crtload[ANALOGTV_V];
203 unsigned int red_values[ANALOGTV_CV_MAX];
204 unsigned int green_values[ANALOGTV_CV_MAX];
205 unsigned int blue_values[ANALOGTV_CV_MAX];
207 unsigned long colors[256];
212 float tint_i, tint_q;
215 int line_hsync[ANALOGTV_V];
218 double line_cb_phase[ANALOGTV_V][4];
220 int channel_change_cycles;
221 double rx_signal_level;
227 } leveltable[ANALOGTV_MAX_LINEHEIGHT+1][ANALOGTV_MAX_LINEHEIGHT+1];
229 /* Only valid during draw. */
230 unsigned random0, random1;
232 const analogtv_reception *const *recs;
235 float *signal_subtotals;
241 analogtv *analogtv_allocate(Display *dpy, Window window);
242 analogtv_input *analogtv_input_allocate(void);
244 /* call if window size changes */
245 void analogtv_reconfigure(analogtv *it);
247 void analogtv_set_defaults(analogtv *it, char *prefix);
248 void analogtv_release(analogtv *it);
249 int analogtv_set_demod(analogtv *it);
250 void analogtv_setup_frame(analogtv *it);
251 void analogtv_setup_sync(analogtv_input *input, int do_cb, int do_ssavi);
252 void analogtv_draw(analogtv *it, double noiselevel,
253 const analogtv_reception *const *recs, unsigned rec_count);
255 int analogtv_load_ximage(analogtv *it, analogtv_input *input,
256 XImage *pic_im, XImage *mask_im,
257 int xoff, int yoff, int width, int height);
259 void analogtv_reception_update(analogtv_reception *inp);
261 void analogtv_setup_teletext(analogtv_input *input);
264 /* Functions for rendering content into an analogtv_input */
266 void analogtv_make_font(Display *dpy, Window window,
267 analogtv_font *f, int w, int h, char *fontname);
268 int analogtv_font_pixel(analogtv_font *f, int c, int x, int y);
269 void analogtv_font_set_pixel(analogtv_font *f, int c, int x, int y, int value);
270 void analogtv_font_set_char(analogtv_font *f, int c, char *s);
271 void analogtv_lcp_to_ntsc(double luma, double chroma, double phase,
275 void analogtv_draw_solid(analogtv_input *input,
276 int left, int right, int top, int bot,
279 void analogtv_draw_solid_rel_lcp(analogtv_input *input,
280 double left, double right,
281 double top, double bot,
282 double luma, double chroma, double phase);
284 void analogtv_draw_char(analogtv_input *input, analogtv_font *f,
285 int c, int x, int y, int ntsc[4]);
286 void analogtv_draw_string(analogtv_input *input, analogtv_font *f,
287 char *s, int x, int y, int ntsc[4]);
288 void analogtv_draw_string_centered(analogtv_input *input, analogtv_font *f,
289 char *s, int x, int y, int ntsc[4]);
291 int analogtv_handle_events (analogtv *it);
293 #ifdef HAVE_XSHM_EXTENSION
294 #define ANALOGTV_DEFAULTS_SHM "*useSHM: True",
296 #define ANALOGTV_DEFAULTS_SHM
300 # define ANALOGTV_DEF_BRIGHTNESS "2"
301 # define ANALOGTV_DEF_CONTRAST "150"
303 /* Need to really crank this up for it to look good on the iPhone screen. */
304 # define ANALOGTV_DEF_BRIGHTNESS "3"
305 # define ANALOGTV_DEF_CONTRAST "400"
308 /* Brightness: useful range is around -75 to 100.
309 Contrast: useful range is around 0 - 500.
310 Color: useful range is around +/- 500.
311 Tint: range is mod 360.
313 The values in the 'analogtv' struct are the resource divided by 100.0,
314 except for tint, which is exact.
317 #define ANALOGTV_DEFAULTS \
320 "*TVBrightness: " ANALOGTV_DEF_BRIGHTNESS, \
321 "*TVContrast: " ANALOGTV_DEF_CONTRAST, \
322 "*Background: Black", \
324 "*geometry: 800x600", \
328 ANALOGTV_DEFAULTS_SHM
330 #define ANALOGTV_OPTIONS \
332 { "-use-cmap", ".use_cmap", XrmoptionSepArg, 0 }, \
333 { "-tv-color", ".TVColor", XrmoptionSepArg, 0 }, \
334 { "-tv-tint", ".TVTint", XrmoptionSepArg, 0 }, \
335 { "-tv-brightness", ".TVBrightness", XrmoptionSepArg, 0 }, \
336 { "-tv-contrast", ".TVContrast", XrmoptionSepArg, 0 },
338 #endif /* _XSCREENSAVER_ANALOGTV_H */