1 /* analogtv, Copyright (c) 2003, 2004 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
18 You'll need these to generate standard NTSC TV signals
21 /* We don't handle interlace here */
24 ANALOGTV_VISLINES=200,
25 ANALOGTV_BOT=ANALOGTV_TOP + ANALOGTV_VISLINES,
27 /* This really defines our sampling rate, 4x the colorburst
28 frequency. Handily equal to the Apple II's dot clock.
29 You could also make a case for using 3x the colorburst freq,
30 but 4x isn't hard to deal with. */
33 /* Each line is 63500 nS long. The sync pulse is 4700 nS long, etc.
34 Define sync, back porch, colorburst, picture, and front porch
36 ANALOGTV_SYNC_START=0,
37 ANALOGTV_BP_START=4700*ANALOGTV_H/63500,
38 ANALOGTV_CB_START=5800*ANALOGTV_H/63500,
39 /* signal[row][ANALOGTV_PIC_START] is the first displayed pixel */
40 ANALOGTV_PIC_START=9400*ANALOGTV_H/63500,
41 ANALOGTV_PIC_LEN=52600*ANALOGTV_H/63500,
42 ANALOGTV_FP_START=62000*ANALOGTV_H/63500,
43 ANALOGTV_PIC_END=ANALOGTV_FP_START,
45 /* TVs scan past the edges of the picture tube, so normally you only
46 want to use about the middle 3/4 of the nominal scan line.
48 ANALOGTV_VIS_START=ANALOGTV_PIC_START + (ANALOGTV_PIC_LEN*1/8),
49 ANALOGTV_VIS_END=ANALOGTV_PIC_START + (ANALOGTV_PIC_LEN*7/8),
50 ANALOGTV_VIS_LEN=ANALOGTV_VIS_END-ANALOGTV_VIS_START,
52 ANALOGTV_HASHNOISE_LEN=6,
54 ANALOGTV_GHOSTFIR_LEN=4,
56 /* analogtv.signal is in IRE units, as defined below: */
57 ANALOGTV_WHITE_LEVEL=100,
58 ANALOGTV_GRAY50_LEVEL=55,
59 ANALOGTV_GRAY30_LEVEL=35,
60 ANALOGTV_BLACK_LEVEL=10,
61 ANALOGTV_BLANK_LEVEL=0,
62 ANALOGTV_SYNC_LEVEL=-40,
65 ANALOGTV_SIGNAL_LEN=ANALOGTV_V*ANALOGTV_H,
67 /* The number of intensity levels we deal with for gamma correction &c */
70 /* MAX_LINEHEIGHT corresponds to 2400 vertical pixels, beyond which
71 it interpolates extra black lines. */
72 ANALOGTV_MAX_LINEHEIGHT=12
76 typedef struct analogtv_input_s {
77 signed char signal[ANALOGTV_V+1][ANALOGTV_H];
82 void (*updater)(struct analogtv_input_s *inp);
84 double next_update_time;
88 typedef struct analogtv_font_s {
94 typedef struct analogtv_reception_s {
96 analogtv_input *input;
102 double ghostfir[ANALOGTV_GHOSTFIR_LEN];
103 double ghostfir2[ANALOGTV_GHOSTFIR_LEN];
108 } analogtv_reception;
111 The rest of this should be considered mostly opaque to the analogtv module.
114 typedef struct analogtv_s {
119 XWindowAttributes xgwa;
122 unsigned int onscreen_signature[ANALOGTV_V];
128 int interlace_counter;
132 /* If you change these, call analogtv_set_demod */
133 double tint_control,color_control,brightness_control,contrast_control;
134 double height_control, width_control, squish_control;
136 double squeezebottom;
142 /* For fast display, set fakeit_top, fakeit_bot to
143 the scanlines (0..ANALOGTV_V) that can be preserved on screen.
144 fakeit_scroll is the number of scan lines to scroll it up,
145 or 0 to not scroll at all. It will DTRT if asked to scroll from
153 int use_shm,use_cmap,use_color;
156 #ifdef HAVE_XSHM_EXTENSION
157 XShmSegmentInfo shm_info;
159 int visdepth,visclass,visbits;
160 int red_invprec, red_shift;
161 int green_invprec, green_shift;
162 int blue_invprec, blue_shift;
163 unsigned int red_mask, green_mask, blue_mask;
166 int usewidth,useheight,xrepl,subwidth;
167 XImage *image; /* usewidth * useheight */
169 int screen_xo,screen_yo; /* centers image in window */
171 int flutter_horiz_desync;
174 struct timeval last_display_time;
178 /* Add hash (in the radio sense, not the programming sense.) These
179 are the small white streaks that appear in quasi-regular patterns
180 all over the screen when someone is running the vacuum cleaner or
181 the blender. We also set shrinkpulse for one period which
182 squishes the image horizontally to simulate the temporary line
183 voltate drop when someone turns on a big motor */
184 double hashnoise_rpm;
185 int hashnoise_counter;
186 int hashnoise_times[ANALOGTV_V];
187 int hashnoise_signal[ANALOGTV_V];
189 int hashnoise_enable;
192 double crtload[ANALOGTV_V];
194 unsigned int red_values[ANALOGTV_CV_MAX];
195 unsigned int green_values[ANALOGTV_CV_MAX];
196 unsigned int blue_values[ANALOGTV_CV_MAX];
198 struct analogtv_yiq_s {
200 } yiq[ANALOGTV_PIC_LEN+10];
202 unsigned long colors[256];
208 int line_hsync[ANALOGTV_V];
211 double line_cb_phase[ANALOGTV_V][4];
213 int channel_change_cycles;
214 double rx_signal_level;
215 double rx_signal[ANALOGTV_SIGNAL_LEN + 2*ANALOGTV_H];
220 } leveltable[ANALOGTV_MAX_LINEHEIGHT+1][ANALOGTV_MAX_LINEHEIGHT+1];
225 analogtv *analogtv_allocate(Display *dpy, Window window);
226 analogtv_input *analogtv_input_allocate(void);
228 /* call if window size changes */
229 void analogtv_reconfigure(analogtv *it);
231 void analogtv_set_defaults(analogtv *it, char *prefix);
232 void analogtv_release(analogtv *it);
233 int analogtv_set_demod(analogtv *it);
234 void analogtv_setup_frame(analogtv *it);
235 void analogtv_setup_sync(analogtv_input *input, int do_cb, int do_ssavi);
236 void analogtv_draw(analogtv *it);
238 int analogtv_load_ximage(analogtv *it, analogtv_input *input, XImage *pic_im);
240 void analogtv_reception_update(analogtv_reception *inp);
242 void analogtv_init_signal(analogtv *it, double noiselevel);
243 void analogtv_add_signal(analogtv *it, analogtv_reception *rec);
245 void analogtv_setup_teletext(analogtv_input *input);
248 /* Functions for rendering content into an analogtv_input */
250 void analogtv_make_font(Display *dpy, Window window,
251 analogtv_font *f, int w, int h, char *fontname);
252 int analogtv_font_pixel(analogtv_font *f, int c, int x, int y);
253 void analogtv_font_set_pixel(analogtv_font *f, int c, int x, int y, int value);
254 void analogtv_font_set_char(analogtv_font *f, int c, char *s);
255 void analogtv_lcp_to_ntsc(double luma, double chroma, double phase,
259 void analogtv_draw_solid(analogtv_input *input,
260 int left, int right, int top, int bot,
263 void analogtv_draw_solid_rel_lcp(analogtv_input *input,
264 double left, double right,
265 double top, double bot,
266 double luma, double chroma, double phase);
268 void analogtv_draw_char(analogtv_input *input, analogtv_font *f,
269 int c, int x, int y, int ntsc[4]);
270 void analogtv_draw_string(analogtv_input *input, analogtv_font *f,
271 char *s, int x, int y, int ntsc[4]);
272 void analogtv_draw_string_centered(analogtv_input *input, analogtv_font *f,
273 char *s, int x, int y, int ntsc[4]);
274 void analogtv_draw_xpm(analogtv *tv, analogtv_input *input,
275 const char * const *xpm, int left, int top);
277 int analogtv_handle_events (analogtv *it);
279 #ifdef HAVE_XSHM_EXTENSION
280 #define ANALOGTV_DEFAULTS_SHM "*useSHM: True",
282 #define ANALOGTV_DEFAULTS_SHM
286 # define ANALOGTV_DEF_BRIGHTNESS "2"
287 # define ANALOGTV_DEF_CONTRAST "150"
289 /* Need to really crank this up for it to look good on the iPhone screen. */
290 # define ANALOGTV_DEF_BRIGHTNESS "3"
291 # define ANALOGTV_DEF_CONTRAST "1000"
294 #define ANALOGTV_DEFAULTS \
297 "*TVBrightness: " ANALOGTV_DEF_BRIGHTNESS, \
298 "*TVContrast: " ANALOGTV_DEF_CONTRAST, \
299 "*Background: Black", \
301 "*geometry: 800x600", \
303 ANALOGTV_DEFAULTS_SHM
305 #define ANALOGTV_OPTIONS \
306 { "-use-cmap", ".use_cmap", XrmoptionSepArg, 0 }, \
307 { "-tv-color", ".TVColor", XrmoptionSepArg, 0 }, \
308 { "-tv-tint", ".TVTint", XrmoptionSepArg, 0 }, \
309 { "-tv-brightness", ".TVBrightness", XrmoptionSepArg, 0 }, \
310 { "-tv-contrast", ".TVContrast", XrmoptionSepArg, 0 },
312 #endif /* _XSCREENSAVER_ANALOGTV_H */