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
15 #include "thread_util.h"
19 You'll need these to generate standard NTSC TV signals
22 /* We don't handle interlace here */
25 ANALOGTV_VISLINES=200,
26 ANALOGTV_BOT=ANALOGTV_TOP + ANALOGTV_VISLINES,
28 /* This really defines our sampling rate, 4x the colorburst
29 frequency. Handily equal to the Apple II's dot clock.
30 You could also make a case for using 3x the colorburst freq,
31 but 4x isn't hard to deal with. */
34 /* Each line is 63500 nS long. The sync pulse is 4700 nS long, etc.
35 Define sync, back porch, colorburst, picture, and front porch
37 ANALOGTV_SYNC_START=0,
38 ANALOGTV_BP_START=4700*ANALOGTV_H/63500,
39 ANALOGTV_CB_START=5800*ANALOGTV_H/63500,
40 /* signal[row][ANALOGTV_PIC_START] is the first displayed pixel */
41 ANALOGTV_PIC_START=9400*ANALOGTV_H/63500,
42 ANALOGTV_PIC_LEN=52600*ANALOGTV_H/63500,
43 ANALOGTV_FP_START=62000*ANALOGTV_H/63500,
44 ANALOGTV_PIC_END=ANALOGTV_FP_START,
46 /* TVs scan past the edges of the picture tube, so normally you only
47 want to use about the middle 3/4 of the nominal scan line.
49 ANALOGTV_VIS_START=ANALOGTV_PIC_START + (ANALOGTV_PIC_LEN*1/8),
50 ANALOGTV_VIS_END=ANALOGTV_PIC_START + (ANALOGTV_PIC_LEN*7/8),
51 ANALOGTV_VIS_LEN=ANALOGTV_VIS_END-ANALOGTV_VIS_START,
53 ANALOGTV_HASHNOISE_LEN=6,
55 ANALOGTV_GHOSTFIR_LEN=4,
57 /* analogtv.signal is in IRE units, as defined below: */
58 ANALOGTV_WHITE_LEVEL=100,
59 ANALOGTV_GRAY50_LEVEL=55,
60 ANALOGTV_GRAY30_LEVEL=35,
61 ANALOGTV_BLACK_LEVEL=10,
62 ANALOGTV_BLANK_LEVEL=0,
63 ANALOGTV_SYNC_LEVEL=-40,
66 ANALOGTV_SIGNAL_LEN=ANALOGTV_V*ANALOGTV_H,
68 /* The number of intensity levels we deal with for gamma correction &c */
71 /* MAX_LINEHEIGHT corresponds to 2400 vertical pixels, beyond which
72 it interpolates extra black lines. */
73 ANALOGTV_MAX_LINEHEIGHT=12
77 typedef struct analogtv_input_s {
78 signed char signal[ANALOGTV_V+1][ANALOGTV_H];
83 void (*updater)(struct analogtv_input_s *inp);
85 double next_update_time;
89 typedef struct analogtv_font_s {
95 typedef struct analogtv_reception_s {
97 analogtv_input *input;
103 double ghostfir[ANALOGTV_GHOSTFIR_LEN];
104 double ghostfir2[ANALOGTV_GHOSTFIR_LEN];
109 } analogtv_reception;
112 The rest of this should be considered mostly opaque to the analogtv module.
115 struct analogtv_yiq_s {
117 } /*yiq[ANALOGTV_PIC_LEN+10] */;
119 typedef struct analogtv_s {
124 XWindowAttributes xgwa;
126 struct threadpool threads;
129 unsigned int onscreen_signature[ANALOGTV_V];
135 int interlace_counter;
139 /* If you change these, call analogtv_set_demod */
140 float tint_control,color_control,brightness_control,contrast_control;
141 float height_control, width_control, squish_control;
149 /* For fast display, set fakeit_top, fakeit_bot to
150 the scanlines (0..ANALOGTV_V) that can be preserved on screen.
151 fakeit_scroll is the number of scan lines to scroll it up,
152 or 0 to not scroll at all. It will DTRT if asked to scroll from
160 int use_shm,use_cmap,use_color;
163 #ifdef HAVE_XSHM_EXTENSION
164 XShmSegmentInfo shm_info;
166 int visdepth,visclass,visbits;
167 int red_invprec, red_shift;
168 int green_invprec, green_shift;
169 int blue_invprec, blue_shift;
170 unsigned int red_mask, green_mask, blue_mask;
173 int usewidth,useheight,xrepl,subwidth;
174 XImage *image; /* usewidth * useheight */
176 int screen_xo,screen_yo; /* centers image in window */
178 int flutter_horiz_desync;
181 struct timeval last_display_time;
185 /* Add hash (in the radio sense, not the programming sense.) These
186 are the small white streaks that appear in quasi-regular patterns
187 all over the screen when someone is running the vacuum cleaner or
188 the blender. We also set shrinkpulse for one period which
189 squishes the image horizontally to simulate the temporary line
190 voltate drop when someone turns on a big motor */
191 double hashnoise_rpm;
192 int hashnoise_counter;
193 int hashnoise_times[ANALOGTV_V];
194 int hashnoise_signal[ANALOGTV_V];
196 int hashnoise_enable;
199 float crtload[ANALOGTV_V];
201 unsigned int red_values[ANALOGTV_CV_MAX];
202 unsigned int green_values[ANALOGTV_CV_MAX];
203 unsigned int blue_values[ANALOGTV_CV_MAX];
205 unsigned long colors[256];
210 float tint_i, tint_q;
213 int line_hsync[ANALOGTV_V];
216 double line_cb_phase[ANALOGTV_V][4];
218 int channel_change_cycles;
219 double rx_signal_level;
225 } leveltable[ANALOGTV_MAX_LINEHEIGHT+1][ANALOGTV_MAX_LINEHEIGHT+1];
227 /* Only valid during draw. */
228 unsigned random0, random1;
230 const analogtv_reception *const *recs;
233 float *signal_subtotals;
239 analogtv *analogtv_allocate(Display *dpy, Window window);
240 analogtv_input *analogtv_input_allocate(void);
242 /* call if window size changes */
243 void analogtv_reconfigure(analogtv *it);
245 void analogtv_set_defaults(analogtv *it, char *prefix);
246 void analogtv_release(analogtv *it);
247 int analogtv_set_demod(analogtv *it);
248 void analogtv_setup_frame(analogtv *it);
249 void analogtv_setup_sync(analogtv_input *input, int do_cb, int do_ssavi);
250 void analogtv_draw(analogtv *it, double noiselevel,
251 const analogtv_reception *const *recs, unsigned rec_count);
253 int analogtv_load_ximage(analogtv *it, analogtv_input *input, XImage *pic_im);
255 void analogtv_reception_update(analogtv_reception *inp);
257 void analogtv_setup_teletext(analogtv_input *input);
260 /* Functions for rendering content into an analogtv_input */
262 void analogtv_make_font(Display *dpy, Window window,
263 analogtv_font *f, int w, int h, char *fontname);
264 int analogtv_font_pixel(analogtv_font *f, int c, int x, int y);
265 void analogtv_font_set_pixel(analogtv_font *f, int c, int x, int y, int value);
266 void analogtv_font_set_char(analogtv_font *f, int c, char *s);
267 void analogtv_lcp_to_ntsc(double luma, double chroma, double phase,
271 void analogtv_draw_solid(analogtv_input *input,
272 int left, int right, int top, int bot,
275 void analogtv_draw_solid_rel_lcp(analogtv_input *input,
276 double left, double right,
277 double top, double bot,
278 double luma, double chroma, double phase);
280 void analogtv_draw_char(analogtv_input *input, analogtv_font *f,
281 int c, int x, int y, int ntsc[4]);
282 void analogtv_draw_string(analogtv_input *input, analogtv_font *f,
283 char *s, int x, int y, int ntsc[4]);
284 void analogtv_draw_string_centered(analogtv_input *input, analogtv_font *f,
285 char *s, int x, int y, int ntsc[4]);
286 void analogtv_draw_xpm(analogtv *tv, analogtv_input *input,
287 const char * const *xpm, int left, int top);
289 int analogtv_handle_events (analogtv *it);
291 #ifdef HAVE_XSHM_EXTENSION
292 #define ANALOGTV_DEFAULTS_SHM "*useSHM: True",
294 #define ANALOGTV_DEFAULTS_SHM
298 # define ANALOGTV_DEF_BRIGHTNESS "2"
299 # define ANALOGTV_DEF_CONTRAST "150"
301 /* Need to really crank this up for it to look good on the iPhone screen. */
302 # define ANALOGTV_DEF_BRIGHTNESS "3"
303 # define ANALOGTV_DEF_CONTRAST "1000"
306 #define ANALOGTV_DEFAULTS \
309 "*TVBrightness: " ANALOGTV_DEF_BRIGHTNESS, \
310 "*TVContrast: " ANALOGTV_DEF_CONTRAST, \
311 "*Background: Black", \
313 "*geometry: 800x600", \
316 ANALOGTV_DEFAULTS_SHM
318 #define ANALOGTV_OPTIONS \
320 { "-use-cmap", ".use_cmap", XrmoptionSepArg, 0 }, \
321 { "-tv-color", ".TVColor", XrmoptionSepArg, 0 }, \
322 { "-tv-tint", ".TVTint", XrmoptionSepArg, 0 }, \
323 { "-tv-brightness", ".TVBrightness", XrmoptionSepArg, 0 }, \
324 { "-tv-contrast", ".TVContrast", XrmoptionSepArg, 0 },
326 #endif /* _XSCREENSAVER_ANALOGTV_H */