00001
00002 #include "bx.h"
00003
00004 static MyX myx;
00005
00006
00007 struct bx_window_stuff {
00008 Window window;
00009
00010 Pixmap back, front;
00011
00012 int x, y;
00013 unsigned width, height;
00014
00015 MyX_Geometry geom;
00016 int win_x, win_y;
00017 unsigned win_width, win_height;
00018
00019 MyX_Handlers handlers;
00020 unsigned long eventMask;
00021 bx_mouse_function on_mouse_move;
00022 bx_mouse_function on_mouse_press, on_mouse_release;
00023 bx_key_function on_key_press, on_key_release;
00024
00025 };
00026
00027 #define BX_MAX_DIR_BUFFER 100000L
00028 #define BX_MAX_DIR_ENTRIES 10000
00029
00030 struct bx_dir_stuff {
00031 char buffer [BX_MAX_DIR_BUFFER ];
00032 char * entries [BX_MAX_DIR_ENTRIES];
00033 int nb_entries;
00034 long nb_chars;
00035 };
00036
00037
00038
00039
00040
00041
00042
00043 int bx_on_io_error (Display * dsiplay UNUSED)
00044 {
00045 printf ("bx to user: good bye !\n");
00046 exit (0);
00047 }
00048
00049 void
00050 bx_init (void)
00051 {
00052 if (-1 == MyX_Init (& myx, "")) {
00053 fprintf (stderr, "bx_init(): failed.\n");
00054 exit (1);
00055 }
00056 MyX_IgnoreAutoRepeat (& myx, 1);
00057 XSetIOErrorHandler (bx_on_io_error);
00058 }
00059
00060 void
00061 bx_clean (void)
00062 {
00063 MyX_Clean (& myx);
00064 }
00065
00066
00067
00068
00069
00070
00071 static void
00072 Window_KeyPress (MyX * myx UNUSED, XEvent * event, void * data)
00073 {
00074 bx_window win;
00075 win.stuff= data;
00076 if (win.stuff->on_key_press) {
00077 unsigned char keycode= event->xkey.keycode;
00078 win.stuff->on_key_press (win, keycode);
00079 }
00080 }
00081
00082 static void
00083 Window_KeyRelease (MyX * myx UNUSED, XEvent * event, void * data)
00084 {
00085 bx_window win;
00086 win.stuff= data;
00087 if (win.stuff->on_key_release) {
00088 unsigned char keycode= event->xkey.keycode;
00089 win.stuff->on_key_release (win, keycode);
00090 }
00091 }
00092
00093 static unsigned
00094 Button_To_ButtonMask (int button) {
00095 switch (button) {
00096 case 1: return Button1Mask;
00097 case 2: return Button2Mask;
00098 case 3: return Button3Mask;
00099 case 4: return Button4Mask;
00100 case 5: return Button5Mask;
00101 default: return 0;
00102 }
00103 }
00104
00105 static void
00106 Window_ButtonPress (MyX * myx UNUSED, XEvent * event, void * data)
00107 {
00108 bx_window win;
00109 win.stuff= data;
00110 if (win.stuff->on_mouse_press) {
00111 bx_mouse mouse;
00112 mouse.xRel= event->xbutton.x; mouse.xAbs= event->xbutton.x_root;
00113 mouse.yRel= event->xbutton.y; mouse.yAbs= event->xbutton.y_root;
00114 mouse.x= mouse.xRel - bx_canvas_x (win);
00115 mouse.y= mouse.xRel - bx_canvas_y (win);
00116 mouse.root= event->xbutton.root;
00117 mouse.child= event->xbutton.window;
00118 mouse.keyMask= event->xbutton.state;
00119 mouse.keyMask |= Button_To_ButtonMask ( event->xbutton.button);
00120 win.stuff->on_mouse_press (win, mouse);
00121 }
00122 }
00123
00124 static void
00125 Window_ButtonRelease (MyX * myx UNUSED, XEvent * event UNUSED, void * data)
00126 {
00127 bx_window win;
00128 win.stuff= data;
00129 if (win.stuff->on_mouse_release) {
00130 bx_mouse mouse;
00131 mouse.xRel= event->xbutton.x; mouse.xAbs= event->xbutton.x_root;
00132 mouse.yRel= event->xbutton.y; mouse.yAbs= event->xbutton.y_root;
00133 mouse.x= mouse.xRel - bx_canvas_x (win);
00134 mouse.y= mouse.xRel - bx_canvas_y (win);
00135 mouse.root= event->xbutton.root;
00136 mouse.child= event->xbutton.window;
00137 mouse.keyMask= event->xbutton.state;
00138 mouse.keyMask |= Button_To_ButtonMask ( event->xbutton.button);
00139 win.stuff->on_mouse_release (win, mouse);
00140 }
00141 }
00142
00143
00144 static void
00145 Window_Motion (MyX * myx UNUSED, XEvent * event UNUSED, void * data)
00146 {
00147 bx_window win;
00148 win.stuff= data;
00149 if (win.stuff->on_mouse_move) {
00150 bx_mouse mouse;
00151 mouse.xRel= event->xbutton.x; mouse.xAbs= event->xbutton.x_root;
00152 mouse.yRel= event->xbutton.y; mouse.yAbs= event->xbutton.y_root;
00153 mouse.x= mouse.xRel - bx_canvas_x (win);
00154 mouse.y= mouse.xRel - bx_canvas_y (win);
00155 mouse.root= event->xbutton.root;
00156 mouse.child= event->xbutton.window;
00157 mouse.keyMask= event->xbutton.state;
00158 win.stuff->on_mouse_move (win, mouse);
00159 }
00160 }
00161
00162
00163
00164
00165
00166
00167 INLINE static void
00168 bx_update_canvas_geometry (bx_window win)
00169 {
00170 win.stuff->x= ((int)win.stuff->win_width - (int)win.stuff->width )/ 2;
00171 win.stuff->y= ((int)win.stuff->win_height - (int)win.stuff->height)/ 2;
00172 }
00173
00174 static void
00175 Window_ConfigureNotify (MyX * myx UNUSED, XEvent * event, void * data)
00176 {
00177 bx_window win;
00178 win.stuff= data;
00179 win.stuff->win_x = event->xconfigure.x;
00180 win.stuff->win_y = event->xconfigure.y;
00181 win.stuff->win_width = event->xconfigure.width;
00182 win.stuff->win_height= event->xconfigure.height;
00183 bx_update_canvas_geometry (win);
00184 }
00185
00186
00187 static void
00188 Window_Expose (MyX * myx UNUSED, XEvent * event, void * data)
00189 {
00190 bx_window win;
00191 if (event->xexpose.count > 0) return;
00192 win.stuff= data;
00193 bx_update_canvas (win);
00194 }
00195
00196 void bx_destroy_window (bx_window window)
00197 {
00198 XDestroyWindow (myx.display, window.stuff->window);
00199 }
00200
00201
00202
00203
00204
00205
00206 bx_window
00207 bx_create_window (char name [], int x, int y, unsigned w, unsigned h)
00208 {
00209 bx_window win;
00210 MyX_Geometry geom;
00211
00212 win.stuff= malloc (sizeof * win.stuff);
00213 if (! win.stuff) {
00214 fprintf (stderr, "bx_create_window () failed: no memory.\n");
00215 exit (1);
00216 }
00217 win.stuff->width = w;
00218 win.stuff->height= h;
00219
00220 MyX_InitHandlers (& win.stuff->handlers);
00221 MyX_SetHandler (& win.stuff->handlers, Expose, Window_Expose);
00222 MyX_SetHandler (& win.stuff->handlers, ConfigureNotify,
00223 Window_ConfigureNotify);
00224
00225 win.stuff->window= MyX_CreateWindow (& myx, & win.stuff->handlers,
00226 win.stuff, myx.root,
00227 x, y, w, h);
00228
00229
00230 bx_move_window (win, x, y);
00231 bx_resize_window (win, w, h);
00232 bx_rename_window (win, name);
00233 MyX_GetGeometry (& myx, win.stuff->window, & geom);
00234 win.stuff->win_x = geom.x;
00235 win.stuff->win_y = geom.x;
00236 win.stuff->win_width = geom.w;
00237 win.stuff->win_height= geom.h;
00238 bx_update_canvas_geometry (win);
00239
00240
00241
00242 if (0) {
00243 Atom wmdelwin = XInternAtom (myx.display, "WM_DELETE_WINDOW", False);
00244 XSetWMProtocols (myx.display, win.stuff->window, & wmdelwin, 1);
00245 }
00246 win.stuff->eventMask= ExposureMask | StructureNotifyMask;
00247 XSelectInput (myx.display, win.stuff->window, win.stuff->eventMask);
00248
00249 win.stuff->on_mouse_press = NULL;
00250 win.stuff->on_mouse_release= NULL;
00251 win.stuff->on_mouse_move = NULL;
00252 win.stuff->on_key_press = NULL;
00253 win.stuff->on_key_release = NULL;
00254
00255 win.stuff->back = XCreatePixmap (myx.display, myx.root, w, h, myx.depth);
00256 win.stuff->front= XCreatePixmap (myx.display, myx.root, w, h, myx.depth);
00257
00258 bx_clear_canvas (win, bx_white ());
00259 bx_set_color (bx_black ());
00260
00261 XMapRaised (myx.display, win.stuff->window);
00262
00263 bx_show_canvas (win, 0);
00264
00265 return win;
00266 }
00267
00268 INLINE void
00269 bx_move_window (bx_window window, int x, int y)
00270 {
00271 XMoveWindow (myx.display, window.stuff->window, x, y);
00272 }
00273
00274 INLINE void
00275 bx_resize_window (bx_window window, unsigned w, unsigned h)
00276 {
00277 XResizeWindow (myx.display, window.stuff->window, w, h);
00278 }
00279
00280 INLINE void
00281 bx_rename_window (bx_window window, char name [])
00282 {
00283 XStoreName (myx.display, window.stuff->window, name);
00284 }
00285
00286 INLINE char *
00287 bx_window_name (bx_window window)
00288 {
00289 static char name [1024];
00290 char * fetched;
00291 XFetchName (myx.display, window.stuff->window, & fetched);
00292 strncpy (name, fetched, 1024);
00293 name [1023]= '\0';
00294 XFree (fetched);
00295 return name;
00296 }
00297
00298
00299
00300
00301
00302
00303 INLINE unsigned bx_canvas_width (bx_window win) { return win.stuff->width; }
00304 INLINE unsigned bx_canvas_height (bx_window win) { return win.stuff->height; }
00305
00306 INLINE int bx_canvas_x (bx_window w) { return w.stuff->x; }
00307 INLINE int bx_canvas_y (bx_window w) { return w.stuff->y; }
00308
00309 INLINE unsigned bx_window_width (bx_window w) { return w.stuff->win_width; }
00310 INLINE unsigned bx_window_height (bx_window w) { return w.stuff->win_height; }
00311
00312 INLINE int bx_window_x (bx_window w) { return w.stuff->win_x; }
00313 INLINE int bx_window_y (bx_window w) { return w.stuff->win_y; }
00314
00315
00316
00317
00318
00319
00320 void
00321 bx_on_key_press (bx_window win, bx_key_function function)
00322 {
00323 MyX_SetHandler (& win.stuff->handlers, KeyPress, Window_KeyPress);
00324 win.stuff->on_key_press= function;
00325 win.stuff->eventMask |= (KeyPressMask);
00326 XSelectInput (myx.display, win.stuff->window, win.stuff->eventMask);
00327 }
00328
00329 void
00330 bx_on_key_release (bx_window win, bx_key_function function)
00331 {
00332 MyX_SetHandler (& win.stuff->handlers, KeyRelease, Window_KeyRelease);
00333 win.stuff->on_key_release= function;
00334 win.stuff->eventMask |= (KeyReleaseMask);
00335 XSelectInput (myx.display, win.stuff->window, win.stuff->eventMask);
00336 }
00337
00338 void
00339 bx_on_mouse_press (bx_window win, bx_mouse_function function)
00340 {
00341 MyX_SetHandler (& win.stuff->handlers, ButtonPress, Window_ButtonPress);
00342 win.stuff->on_mouse_press= function;
00343 win.stuff->eventMask |= (ButtonPressMask);
00344 XSelectInput (myx.display, win.stuff->window, win.stuff->eventMask);
00345 }
00346 void
00347 bx_on_mouse_release (bx_window win, bx_mouse_function function)
00348 {
00349 MyX_SetHandler (& win.stuff->handlers, ButtonRelease, Window_ButtonRelease);
00350 win.stuff->on_mouse_release= function;
00351 win.stuff->eventMask |= (ButtonReleaseMask);
00352 XSelectInput (myx.display, win.stuff->window, win.stuff->eventMask);
00353 }
00354
00355 void
00356 bx_on_mouse_move (bx_window win, bx_mouse_function function)
00357 {
00358 MyX_SetHandler (& win.stuff->handlers, MotionNotify, Window_Motion);
00359 win.stuff->on_mouse_move= function;
00360 win.stuff->eventMask |= (PointerMotionMask);
00361 XSelectInput (myx.display, win.stuff->window, win.stuff->eventMask);
00362 }
00363
00364
00365
00366
00367
00368
00369 void
00370 bx_loop (void)
00371 {
00372 MyX_EventLoop (& myx);
00373 }
00374
00375
00376
00377
00378
00379
00380 static INLINE void
00381 bx_draw_circle_aux (Drawable d, GC gc, int x, int y,
00382 unsigned w, unsigned h, int filled)
00383 {
00384 if (filled)
00385 XFillArc (myx.display, d, gc, x, y, w, h, 0, 360*64);
00386 else
00387 XDrawArc (myx.display, d, gc, x, y, w-1, h-1, 0, 360*64);
00388 }
00389
00390 static INLINE void
00391 bx_draw_circle_sys (bx_window win, int x, int y,
00392 unsigned w, unsigned h, int filled)
00393 {
00394 bx_draw_circle_aux (win.stuff->window, myx.gc_sys,
00395 x, y, w, h, filled);
00396 }
00397
00398 INLINE void
00399 bx_draw_circle (bx_window win, int x, int y,
00400 unsigned w, unsigned h, int filled)
00401 {
00402 bx_draw_circle_aux (win.stuff->back, myx.gc,
00403 x, y, w, h, filled);
00404 }
00405
00406
00407
00408
00409
00410
00411
00412 static INLINE void
00413 bx_draw_arc_aux (Drawable d, GC gc, int x, int y,
00414 unsigned w, unsigned h,
00415 double a, double da, int filled)
00416 {
00417 if (filled) XFillArc (myx.display,d,gc, x, y, w, h, a*64,da*64);
00418 else XDrawArc (myx.display,d,gc, x, y, w-1, h-1, a*64,da*64);
00419 }
00420
00421 static INLINE void
00422 bx_draw_arc_sys (bx_window win, int x, int y,
00423 unsigned w, unsigned h,
00424 double a, double da, int filled)
00425 {
00426 bx_draw_arc_aux (win.stuff->window, myx.gc_sys,
00427 x, y, w, h, a, da, filled);
00428 }
00429
00430 INLINE void
00431 bx_draw_arc (bx_window win, int x, int y,
00432 unsigned w, unsigned h,
00433 double a, double da, int filled)
00434 {
00435 bx_draw_arc_aux (win.stuff->back, myx.gc,
00436 x, y, w, h, a, da, filled);
00437 }
00438
00439
00440
00441
00442
00443
00444
00445 INLINE static void
00446 bx_draw_point_aux(Drawable d, GC gc, int x, int y)
00447 {
00448 XDrawPoint (myx.display, d, gc, x, y);
00449 }
00450
00451 INLINE static void
00452 bx_draw_point_sys(bx_window win, int x, int y)
00453 {
00454 bx_draw_point_aux (win.stuff->window, myx.gc_sys, x, y);
00455 }
00456
00457 INLINE void
00458 bx_draw_point(bx_window win, int x, int y)
00459 {
00460 bx_draw_point_aux (win.stuff->back, myx.gc, x, y);
00461 }
00462
00463
00464
00465
00466
00467
00468 static INLINE void
00469 bx_draw_line_aux (Drawable d, GC gc, int x1, int y1, int x2, int y2)
00470 {
00471 XDrawLine (myx.display, d, gc, x1, y1, x2, y2);
00472 }
00473
00474 static INLINE void
00475 bx_draw_line_sys (bx_window win, int x1, int y1, int x2, int y2)
00476 {
00477 bx_draw_line_aux (win.stuff->window, myx.gc_sys, x1, y1, x2, y2);
00478 }
00479
00480 INLINE void
00481 bx_draw_line (bx_window win, int x1, int y1, int x2, int y2)
00482 {
00483 bx_draw_line_aux (win.stuff->back, myx.gc, x1, y1, x2, y2);
00484 }
00485
00486
00487
00488
00489
00490
00491 static INLINE void
00492 bx_draw_box_aux (Drawable d, GC gc, int x, int y,
00493 unsigned w, unsigned h, int filled)
00494 {
00495 if (filled) XFillRectangle (myx.display, d, gc, x, y, w, h);
00496 else XDrawRectangle (myx.display, d, gc, x, y, w-1, h-1);
00497 }
00498
00499 static INLINE void
00500 bx_draw_box_sys (bx_window win, int x, int y,
00501 unsigned w, unsigned h, int filled)
00502 {
00503 bx_draw_box_aux (win.stuff->window, myx.gc_sys, x, y, w, h, filled);
00504 }
00505
00506 INLINE void
00507 bx_draw_box (bx_window win, int x, int y,
00508 unsigned w, unsigned h, int filled)
00509 {
00510 bx_draw_box_aux (win.stuff->back, myx.gc, x, y, w, h, filled);
00511 }
00512
00513
00514
00515
00516
00517
00518 #define BX_MAX_POINTS 1024
00519
00520 static void
00521 bx_draw_polygon_aux (Drawable d, GC gc, int n, int x[], int y[], int filled)
00522 {
00523 XPoint points [BX_MAX_POINTS+1];
00524 int k;
00525 if (n > BX_MAX_POINTS) {
00526 fprintf (stderr, "bx_draw_polygon() failed: "
00527 "number of points > %d.\n", BX_MAX_POINTS);
00528 exit (1);
00529 }
00530 for (k= 0; k < n; k++) {
00531 points[k].x= x[k];
00532 points[k].y= y[k];
00533 }
00534 points [n].x= x [0];
00535 points [n].y= y [0];
00536 if (filled) XFillPolygon (myx.display, d, gc, points, n+1,
00537 Complex, CoordModeOrigin);
00538 else XDrawLines (myx.display, d, gc, points, n+1,
00539 CoordModeOrigin);
00540 }
00541
00542 static INLINE void
00543 bx_draw_polygon_sys (bx_window win, int n, int x[], int y[], int filled)
00544 {
00545 bx_draw_polygon_aux (win.stuff->window, myx.gc_sys, n, x, y, filled);
00546 }
00547
00548 INLINE void
00549 bx_draw_polygon (bx_window win, int n, int x[], int y[], int filled)
00550 {
00551 bx_draw_polygon_aux (win.stuff->back, myx.gc, n, x, y, filled);
00552 }
00553
00554 #undef BX_MAX_POINTS
00555
00556
00557
00558
00559
00560
00561 static INLINE void
00562 bx_draw_text_aux (Drawable d, GC gc, int x, int y, char text [])
00563 {
00564 int length= strlen (text);
00565 XDrawString (myx.display, d, gc, x, y, text, length);
00566 }
00567
00568 static INLINE void
00569 bx_draw_text_sys (bx_window win, int x, int y, char text [])
00570 {
00571 bx_draw_text_aux (win.stuff->window, myx.gc_sys, x, y, text);
00572 }
00573
00574 INLINE void
00575 bx_draw_text (bx_window win, int x, int y, char text [])
00576 {
00577 bx_draw_text_aux (win.stuff->back, myx.gc, x, y, text);
00578 }
00579
00580
00581
00582
00583
00584
00585 #define BX_MAX_BUF 2048
00586
00587 static INLINE void
00588 bx_draw_text_aux_f (Drawable d, GC gc, int x, int y, char format [], ...)
00589 {
00590 char buffer [BX_MAX_BUF];
00591 va_list args;
00592 va_start (args, format);
00593 vsprintf (buffer, format, args);
00594 va_end (args);
00595 bx_draw_text_aux (d, gc, x, y, buffer);
00596 }
00597
00598 static INLINE void
00599 bx_draw_text_sys_f (bx_window win, int x, int y, char format [], ...)
00600 {
00601 char buffer [BX_MAX_BUF];
00602 va_list args;
00603 va_start (args, format);
00604 vsprintf (buffer, format, args);
00605 va_end (args);
00606 bx_draw_text_aux (win.stuff->window, myx.gc_sys, x, y, buffer);
00607 }
00608
00609 INLINE void
00610 bx_draw_text_f (bx_window win, int x, int y, char format [], ...)
00611 {
00612 char buffer [BX_MAX_BUF];
00613 va_list args;
00614 va_start (args, format);
00615 vsprintf (buffer, format, args);
00616 va_end (args);
00617 bx_draw_text_aux (win.stuff->back, myx.gc, x, y, buffer);
00618 }
00619
00620 #undef BX_MAX_BUF
00621
00622
00623
00624
00625
00626
00627
00628 #define BX_MIDPOINT(M,A,B) { M.x=(A.x+B.x)/2.0; M.y=(A.y+B.y)/2.0; }
00629 #define BX_3RDPOINT(M,A,B) { M.x= (2.*A.x+B.x)/3.; M.y= (2.*A.y+B.y)/3.; }
00630
00631 void
00632 bx_draw_bezier (bx_window window,
00633 int x0, int y0, int x1, int y1,
00634 int x2, int y2, int x3, int y3)
00635 {
00636 struct { double x, y; } v, a[1000], b[1000], *src= a, *dst= b, *tmp;
00637 int max_src= 3, k_src, k_dst, k, level, nb_levels= 5;
00638
00639 a[0].x = x0; a[1].x = x1; a[2].x = x2; a[3].x = x3; b[0].x= x0;
00640 a[0].y = y0; a[1].y = y1; a[2].y = y2; a[3].y = y3; b[0].y= y0;
00641
00642 for(level= 0; level < nb_levels; level++) {
00643 for (k_src= k_dst= 0; k_src < max_src; k_src+= 3, k_dst+= 6) {
00644 BX_MIDPOINT (v , src[k_src+1], src[k_src+2]);
00645 BX_MIDPOINT (dst[k_dst+1], src[k_src+0], src[k_src+1]);
00646 BX_MIDPOINT (dst[k_dst+5], src[k_src+2], src[k_src+3]);
00647 BX_MIDPOINT (dst[k_dst+2], dst[k_dst+1], v );
00648 BX_MIDPOINT (dst[k_dst+4], dst[k_dst+5], v );
00649 BX_MIDPOINT (dst[k_dst+3], dst[k_dst+2], dst[k_dst+4]);
00650 dst [k_dst+6]= src [k_src+3];
00651 }
00652 tmp= src; src= dst; dst= tmp;
00653 max_src= k_dst;
00654 }
00655
00656 for (k= 0; k < max_src; k++) {
00657 bx_draw_line (window,
00658 src [k+0].x, src [k+0].y,
00659 src [k+1].x, src [k+1].y);
00660 }
00661 }
00662
00663 void
00664 bx_draw_curve (bx_window window, int n, int x [], int y [])
00665 {
00666 int k;
00667 struct { double x,y; } p, q, r, t, a, b, c;
00668 if (n == 0) return;
00669 if (n == 1) { bx_draw_point (window, x[0], y [0]); return; }
00670 if (n == 2) { bx_draw_line (window, x[0], y [0], x[1], y[1]); return; }
00671
00672 a.x= x [0]; b.x= x [1]; c.x= x [2];
00673 a.y= y [0]; b.y= y [1]; c.y= y [2];
00674 BX_3RDPOINT (p, a, b); BX_3RDPOINT (r, b, c);
00675 BX_3RDPOINT (q, b, a); BX_MIDPOINT (t, q, r);
00676 bx_draw_bezier (window, a.x, a.y, p.x, p.y, q.x, q.y, t.x, t.y);
00677 for (k= 3; k < n; k++) {
00678 a= t; p= r; BX_3RDPOINT (q, c, b); b=c;
00679 c.x= x [k]; c.y= y [k];
00680 BX_3RDPOINT (r, b, c);
00681 BX_MIDPOINT (t, q, r);
00682 bx_draw_bezier (window, a.x, a.y, p.x, p.y, q.x, q.y, t.x, t.y);
00683 }
00684 a= t; p= r; BX_3RDPOINT (q, c, b);
00685 bx_draw_bezier (window, a.x, a.y, p.x, p.y, q.x, q.y, c.x, c.y);
00686 }
00687
00688 #undef BX_MIDPOINT
00689 #undef BX_3RDPOINT
00690
00691
00692
00693
00694
00695
00696
00697 INLINE bx_color
00698 bx_rgb_to_color (unsigned char r, unsigned char g, unsigned char b)
00699 {
00700 bx_color color;
00701 color.pixel= MyX_RGB (& myx, r, g, b);
00702 return color;
00703 }
00704
00705 INLINE bx_color
00706 bx_mean_color (bx_color c1, bx_color c2)
00707 {
00708 bx_color color;
00709 color.pixel= MyX_AverageColors (& myx, c1.pixel, c2.pixel);
00710 return color;
00711 }
00712
00713 INLINE bx_color
00714 bx_blend_color (bx_color c1, double alpha, bx_color c2)
00715 {
00716 bx_color color;
00717 color.pixel= MyX_BlendColors (& myx, c1.pixel, alpha, c2.pixel);
00718 return color;
00719 }
00720
00721
00722 INLINE bx_color bx_white(void){return bx_rgb_to_color(0xFF,0xFF,0xFF);}
00723 INLINE bx_color bx_black(void){return bx_rgb_to_color(0x00,0x00,0x00);}
00724
00725 INLINE bx_color bx_gray (void){return bx_rgb_to_color(0x80,0x80,0x80);}
00726 INLINE bx_color bx_pale_gray(void){return bx_rgb_to_color(0xC0,0xC0,0xC0);}
00727 INLINE bx_color bx_dark_gray(void){return bx_rgb_to_color(0x40,0x40,0x40);}
00728
00729 INLINE bx_color bx_red (void){return bx_rgb_to_color(0xFF,0x00,0x00);}
00730 INLINE bx_color bx_pale_red(void){return bx_rgb_to_color(0xFF,0x80,0x80);}
00731 INLINE bx_color bx_dark_red(void){return bx_rgb_to_color(0x80,0x00,0x00);}
00732
00733 INLINE bx_color bx_green (void){return bx_rgb_to_color(0x00,0xFF,0x00);}
00734 INLINE bx_color bx_pale_green(void){return bx_rgb_to_color(0x80,0xFF,0x80);}
00735 INLINE bx_color bx_dark_green(void){return bx_rgb_to_color(0x00,0x80,0x00);}
00736
00737 INLINE bx_color bx_blue (void){return bx_rgb_to_color(0x00,0x00,0xFF);}
00738 INLINE bx_color bx_pale_blue(void){return bx_rgb_to_color(0x80,0x80,0xFF);}
00739 INLINE bx_color bx_dark_blue(void){return bx_rgb_to_color(0x00,0x00,0x80);}
00740
00741 INLINE bx_color bx_yellow (void){return bx_rgb_to_color(0xFF,0xFF,0x00);}
00742 INLINE bx_color bx_pale_yellow(void){return bx_rgb_to_color(0xFF,0xFF,0xC0);}
00743 INLINE bx_color bx_dark_yellow(void){return bx_rgb_to_color(0x80,0x80,0x00);}
00744
00745 INLINE bx_color bx_cyan (void){return bx_rgb_to_color(0x00,0xFF,0xFF);}
00746 INLINE bx_color bx_pale_cyan(void){return bx_rgb_to_color(0xC0,0xFF,0xFF);}
00747 INLINE bx_color bx_dark_cyan(void){return bx_rgb_to_color(0x00,0x80,0x80);}
00748
00749 INLINE bx_color bx_magenta (void){return bx_rgb_to_color(0xFF,0x00,0xFF);}
00750 INLINE bx_color bx_pale_magenta(void){return bx_rgb_to_color(0xFF,0xC0,0xFF);}
00751 INLINE bx_color bx_dark_magenta(void){return bx_rgb_to_color(0xC0,0x00,0xC0);}
00752
00753 INLINE bx_color bx_orange (void){return bx_rgb_to_color(0xFF,0x80,0x00);}
00754 INLINE bx_color bx_pale_orange(void){return bx_rgb_to_color(0xFF,0xC0,0x80);}
00755 INLINE bx_color bx_dark_orange(void){return bx_rgb_to_color(0x80,0x40,0x00);}
00756
00757 INLINE bx_color bx_pink (void){return bx_rgb_to_color(0xFF,0x00,0x80);}
00758 INLINE bx_color bx_pale_pink(void){return bx_rgb_to_color(0xFF,0x80,0xC0);}
00759 INLINE bx_color bx_dark_pink(void){return bx_rgb_to_color(0x80,0x00,0x40);}
00760
00761 INLINE bx_color bx_violet (void){return bx_rgb_to_color(0x80,0x00,0xFF);}
00762 INLINE bx_color bx_pale_violet(void){return bx_rgb_to_color(0xC0,0x80,0xFF);}
00763 INLINE bx_color bx_dark_violet(void){return bx_rgb_to_color(0x40,0x00,0x80);}
00764
00765 INLINE bx_color bx_azure (void){return bx_rgb_to_color (0x00, 0x80,0xFF);}
00766 INLINE bx_color bx_pale_azure(void){return bx_rgb_to_color (0x80, 0xC0,0xFF);}
00767 INLINE bx_color bx_dark_azure(void){return bx_rgb_to_color (0x00, 0x40,0x80);}
00768
00769 INLINE bx_color bx_spring (void){return bx_rgb_to_color (0x00, 0xFF,0x80);}
00770 INLINE bx_color bx_pale_spring(void){return bx_rgb_to_color (0x80, 0xFF,0xC0);}
00771 INLINE bx_color bx_dark_spring(void){return bx_rgb_to_color (0x00, 0x80,0x40);}
00772
00773 INLINE bx_color bx_lawn (void){return bx_rgb_to_color (0x80, 0xFF,0x00);}
00774 INLINE bx_color bx_pale_lawn(void){return bx_rgb_to_color (0xC0, 0xFF,0x80);}
00775 INLINE bx_color bx_dark_lawn(void){return bx_rgb_to_color (0x40, 0x80,0x00);}
00776
00777
00778
00779
00780
00781
00782
00783
00784 static INLINE void
00785 bx_set_color_aux (GC gc, bx_color color)
00786 {
00787 XSetForeground (myx.display, gc, color.pixel);
00788 }
00789
00790 static INLINE void
00791 bx_set_color_sys (bx_color color)
00792 {
00793 bx_set_color_aux (myx.gc_sys, color);
00794 }
00795
00796 INLINE void
00797 bx_set_color (bx_color color)
00798 {
00799 bx_set_color_aux (myx.gc, color);
00800 }
00801
00802
00803
00804
00805
00806 static INLINE void
00807 bx_set_rgb_aux (GC gc, unsigned char r, unsigned char g, unsigned char b)
00808 {
00809 bx_color color= bx_rgb_to_color (r, g, b);
00810 bx_set_color_aux (gc, color);
00811 }
00812
00813 static INLINE void
00814 bx_set_rgb_sys (unsigned char r, unsigned char g, unsigned char b)
00815 {
00816 bx_set_rgb_aux (myx.gc_sys, r, g, b);
00817 }
00818
00819 INLINE void
00820 bx_set_rgb (unsigned char r, unsigned char g, unsigned char b)
00821 {
00822 bx_set_rgb_aux (myx.gc, r, g, b);
00823 }
00824
00825
00826
00827
00828
00829
00830 static INLINE void
00831 bx_set_line_width_aux (GC gc, unsigned width)
00832 {
00833 XSetLineAttributes (myx.display, gc, width,
00834 LineSolid, CapRound, JoinMiter);
00835 }
00836
00837 static INLINE void
00838 bx_set_line_width_sys (unsigned width)
00839 {
00840 bx_set_line_width_aux (myx.gc_sys, width);
00841 }
00842
00843 INLINE void
00844 bx_set_line_width (unsigned width)
00845 {
00846 bx_set_line_width_aux (myx.gc, width);
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856 INLINE static void
00857 bx_draw_rulers (bx_window win)
00858 {
00859 int x= win.stuff->x;
00860 int y= win.stuff->y;
00861 int xr= x + win.stuff->width;
00862 int yr= y + win.stuff->height;
00863
00864 unsigned k;
00865 int mark;
00866 bx_set_color_sys (bx_blue());
00867 for (k= 0; k <= win.stuff->width; k+= 10) {
00868 mark= (k % 50 == 0);
00869 bx_draw_line_sys (win, x+k, y -1, x+k, mark ? y -10 : y -5);
00870 bx_draw_line_sys (win, x+k, yr+1, x+k, mark ? yr+10 : yr+5);
00871 if (! mark) continue;
00872 bx_draw_text_sys_f (win, x+k-20, y -15, "%4d", k);
00873 bx_draw_text_sys_f (win, x+k-20, yr+25, "%4d", k);
00874 }
00875 for (k= 0; k <= win.stuff->height; k+= 10) {
00876 mark= (k % 50 == 0);
00877 bx_draw_line_sys (win, x -1, y+k, mark ? x -10 : x -5, y+k);
00878 bx_draw_line_sys (win, xr+1, y+k, mark ? xr+10 : xr+5, y+k);
00879 if (! mark) continue;
00880 bx_draw_text_sys_f (win, x -40, y+k+5, "%4d", k);
00881 bx_draw_text_sys_f (win, xr+15, y+k+5, "%4d", k);
00882 }
00883 bx_draw_text_sys (win, x + 10, y - 30,
00884 "Programmed with Basic-X library");
00885 bx_draw_text_sys (win, x + 10, yr + 30 + 10,
00886 "bx-lib version 1.0 (c) Regis Barbanchon 2008");
00887 }
00888
00889
00890
00891
00892
00893
00894 INLINE static void
00895 bx_draw_suburb (bx_window win)
00896 {
00897 int x= win.stuff->x;
00898 int y= win.stuff->y;
00899 int xr= x + win.stuff->width;
00900 int yr= y + win.stuff->height;
00901
00902 if (x > 0) {
00903 bx_set_color_sys (bx_gray ());
00904 bx_draw_box_sys (win, 0, 0, x , win.stuff->win_height, 1);
00905 bx_draw_box_sys (win, xr, 0, x+1, win.stuff->win_height, 1);
00906 }
00907 if (y > 0) {
00908 bx_draw_box_sys (win, x, 0, win.stuff->width, y , 1);
00909 bx_draw_box_sys (win, x, yr, win.stuff->width, y+1, 1);
00910 }
00911 }
00912
00913
00914
00915
00916
00917
00918 INLINE void
00919 bx_update_canvas (bx_window win)
00920 {
00921 XCopyArea (myx.display,
00922 win.stuff->front, win.stuff->window, myx.gc,
00923 0, 0, win.stuff->width, win.stuff->height,
00924 win.stuff->x, win.stuff->y);
00925
00926 bx_draw_suburb (win);
00927 bx_draw_rulers (win);
00928 }
00929
00930
00931
00932
00933
00934 void
00935 bx_clear_canvas (bx_window win, bx_color color)
00936 {
00937 bx_set_color_sys (color);
00938 bx_draw_box_aux (win.stuff->back, myx.gc_sys,
00939 0, 0,
00940 bx_canvas_width (win),
00941 bx_canvas_height (win), 1);
00942 }
00943
00944
00945
00946
00947
00948
00949 INLINE void
00950 bx_wait (unsigned long msecs)
00951 {
00952 struct timeval max_delay;
00953 max_delay.tv_sec = msecs / 1000;
00954 max_delay.tv_usec= (msecs % 1000) * 1000;
00955 MyX_WaitEvents (& myx, & max_delay);
00956 }
00957
00958 INLINE void
00959 bx_swap_canvas (bx_window win, unsigned long msecs)
00960 {
00961 struct timeval max_delay;
00962 Pixmap p;
00963
00964 p= win.stuff->back;
00965 win.stuff->back= win.stuff->front;
00966 win.stuff->front= p;
00967
00968 bx_update_canvas (win);
00969
00970 max_delay.tv_sec = msecs / 1000;
00971 max_delay.tv_usec= (msecs % 1000) * 1000;
00972
00973 MyX_WaitEvents (& myx, & max_delay);
00974
00975 }
00976
00977 INLINE void
00978 bx_show_canvas (bx_window win, unsigned long msecs)
00979 {
00980 struct timeval max_delay;
00981
00982 XCopyArea (myx.display,
00983 win.stuff->back, win.stuff->front, myx.gc_sys,
00984 0, 0, win.stuff->width, win.stuff->height, 0, 0);
00985
00986 bx_update_canvas (win);
00987
00988 max_delay.tv_sec = msecs / 1000;
00989 max_delay.tv_usec= (msecs % 1000) * 1000;
00990
00991 MyX_WaitEvents (& myx, & max_delay);
00992
00993 }
00994
00995
00996
00997
00998
00999
01000
01001 INLINE bx_image
01002 bx_load_image (int transp, char name [])
01003 {
01004 bx_image image;
01005 int status;
01006
01007 image.stuff= malloc (sizeof * image.stuff);
01008 if (! image.stuff) {
01009 fprintf (stderr, "bx_load_image() failed: no memory.\n");
01010 exit (1);
01011 }
01012 status= MyX_LoadSprite (& myx, name, image.stuff, transp);
01013 if (status) {
01014 fprintf (stderr, "bx_load_image() failed for file %s\n", name);
01015 free (image.stuff);
01016 exit (1);
01017 }
01018 return image;
01019 }
01020
01021 #define BX_MAX_BUF 2048
01022
01023 INLINE bx_image
01024 bx_load_image_f (int transp, char format [], ...)
01025 {
01026 char buffer [BX_MAX_BUF];
01027 va_list args;
01028
01029 va_start (args, format);
01030 vsprintf (buffer, format, args);
01031 va_end (args);
01032 return bx_load_image (transp, buffer);
01033 }
01034
01035 #undef BX_MAX_BUF
01036
01037
01038
01039
01040
01041
01042 INLINE unsigned
01043 bx_image_width (bx_image image)
01044 {
01045 return image.stuff->width;
01046 }
01047
01048 INLINE unsigned
01049 bx_image_height (bx_image image)
01050 {
01051 return image.stuff->height;
01052 }
01053
01054
01055
01056
01057
01058
01059 INLINE void
01060 bx_flip_image (bx_image image, int xflip, int yflip)
01061 {
01062 MyX_XYFlipSprite (& myx, image.stuff, xflip, yflip);
01063 }
01064
01065 INLINE void
01066 bx_draw_image (bx_window win, bx_image image, int x, int y)
01067 {
01068 MyX_PutSprite (& myx, win.stuff->back,
01069 myx.gc_sys, image.stuff, x, y);
01070 }
01071
01072 INLINE void
01073 bx_draw_image_fx (bx_window win, bx_image image, int x, int y, unsigned mode)
01074 {
01075 MyX_PutFxSprite (& myx, win.stuff->back,
01076 myx.gc_sys, mode, image.stuff, x, y);
01077 }
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 bx_mouse
01104 bx_read_mouse (bx_window win) {
01105 bx_mouse mouse;
01106
01107 XQueryPointer (myx.display, win.stuff->window,
01108 & mouse.root, & mouse.child,
01109 & mouse.xAbs, & mouse.yAbs,
01110 & mouse.xRel, & mouse.yRel,
01111 & mouse.keyMask);
01112
01113 mouse.x = mouse.xRel - win.stuff->x;
01114 mouse.y = mouse.yRel - win.stuff->y;
01115
01116 return mouse;
01117 }
01118
01119 INLINE int bx_mouse_x (bx_mouse mouse) { return mouse.x; }
01120 INLINE int bx_mouse_xcanvas (bx_mouse mouse) { return mouse.x; }
01121 INLINE int bx_mouse_xwindow (bx_mouse mouse) { return mouse.xRel; }
01122 INLINE int bx_mouse_xscreen (bx_mouse mouse) { return mouse.xAbs; }
01123
01124 INLINE int bx_mouse_y (bx_mouse mouse) { return mouse.y; }
01125 INLINE int bx_mouse_ycanvas (bx_mouse mouse) { return mouse.y; }
01126 INLINE int bx_mouse_ywindow (bx_mouse mouse) { return mouse.yRel; }
01127 INLINE int bx_mouse_yscreen (bx_mouse mouse) { return mouse.yAbs; }
01128
01129 INLINE int bx_mouse_b1 (bx_mouse m){ return !!(m.keyMask & Button1Mask); }
01130 INLINE int bx_mouse_b2 (bx_mouse m){ return !!(m.keyMask & Button2Mask); }
01131 INLINE int bx_mouse_b3 (bx_mouse m){ return !!(m.keyMask & Button3Mask); }
01132 INLINE int bx_mouse_b4 (bx_mouse m){ return !!(m.keyMask & Button4Mask); }
01133 INLINE int bx_mouse_b5 (bx_mouse m){ return !!(m.keyMask & Button5Mask); }
01134
01135 INLINE int bx_mouse_shift (bx_mouse m){ return !!(m.keyMask & ShiftMask); }
01136 INLINE int bx_mouse_ctrl (bx_mouse m){ return !!(m.keyMask & ControlMask); }
01137 INLINE int bx_mouse_alt (bx_mouse m){ return !!(m.keyMask & Mod1Mask); }
01138 INLINE int bx_mouse_altgr (bx_mouse m){ return !!(m.keyMask & Mod5Mask); }
01139
01140
01141
01142
01143
01144
01145 INLINE bx_key
01146 bx_read_key (void)
01147 {
01148 bx_key key;
01149 XQueryKeymap (myx.display, (char *) key.bits);
01150 return key;
01151 }
01152
01153 char *
01154 bx_keycode_to_keyname (unsigned char keycode)
01155 {
01156 int keysym= XKeycodeToKeysym (myx.display, keycode, 0);
01157 return XKeysymToString (keysym);
01158 }
01159
01160 unsigned char
01161 bx_keyname_to_keycode (char keyname [])
01162 {
01163 int keysym= XStringToKeysym (keyname);
01164 return XKeysymToKeycode (myx.display, keysym);
01165 }
01166
01167 INLINE int
01168 bx_keycode_pressed (bx_key key, unsigned char keycode)
01169 {
01170 unsigned char num_byte= (keycode & 0xFF) / CHAR_BIT;
01171 unsigned char num_bit = (keycode & 0xFF) % CHAR_BIT;
01172 return !! (key.bits [num_byte] & (1 << num_bit));
01173 }
01174
01175 INLINE int
01176 bx_keyname_pressed (bx_key key, char keyname [])
01177 {
01178 unsigned char keycode= bx_keyname_to_keycode (keyname);
01179 return bx_keycode_pressed (key, keycode);
01180 }
01181
01182 char *
01183 bx_keynames (bx_key key)
01184 {
01185 static char names [4096];
01186 int k, offset= 0;
01187 for (k= 0; k < 32 * CHAR_BIT; k++) {
01188 if (bx_keycode_pressed (key, k)) {
01189 char * keyname= bx_keycode_to_keyname (k);
01190 sprintf (names + offset, "%s ", keyname);
01191 offset += strlen (keyname) + 1;
01192 }
01193 }
01194 return names;
01195 }
01196
01197 int bx_key_number (bx_key key) {
01198 int k, number= 0;
01199 for (k= 0; k < 32 * CHAR_BIT; k++) {
01200 number += bx_keycode_pressed (key, k);
01201 }
01202 return number;
01203 }
01204
01205 INLINE void
01206 bx_set_autorepeat (int activate)
01207 {
01208 MyX_IgnoreAutoRepeat (& myx, ! activate);
01209 }
01210
01211
01212
01213
01214
01215
01216 static int
01217 bx_compare_filenames (void const * a, void const * b)
01218 {
01219 char * const * x= a;
01220 char * const * y= b;
01221
01222 return strcmp (* x, * y);
01223 }
01224
01225 bx_dir
01226 bx_open_dir (char path [])
01227 {
01228 bx_dir rep;
01229 DIR * dir;
01230 struct dirent * dirent;
01231 long length;
01232
01233 rep.stuff= malloc (sizeof * rep.stuff);
01234 if (! rep.stuff) {
01235 fprintf (stderr, "bx_open_dir() failed: no memory.\n");
01236 exit (1);
01237 }
01238 dir= opendir (path);
01239 if (! dir) {
01240 fprintf (stderr, "bx_open_dir() failed for %s.\n", path);
01241 free (dir); exit (1);
01242 }
01243 rep.stuff->nb_chars = 0;
01244 rep.stuff->nb_entries= 0;
01245 for (;;) {
01246 dirent= readdir (dir);
01247 if (! dirent) break;
01248
01249 if (! strcmp (dirent->d_name, "." )) continue;
01250 if (! strcmp (dirent->d_name, "..")) continue;
01251
01252 if (rep.stuff->nb_entries >= BX_MAX_DIR_ENTRIES) {
01253 fprintf (stderr, "bx_open_dir() failed: too many files.\n");
01254 free (dir); exit (1);
01255 }
01256 length= strlen (dirent->d_name);
01257 if (rep.stuff->nb_chars + length + 1 > BX_MAX_DIR_BUFFER) {
01258 fprintf (stderr, "bx_open_dir() failed: filenames too long.\n");
01259 free (dir); exit (1);
01260 }
01261 strcpy (rep.stuff->buffer + rep.stuff->nb_chars, dirent->d_name);
01262 rep.stuff->entries [rep.stuff->nb_entries]=
01263 rep.stuff->buffer + rep.stuff->nb_chars;
01264 rep.stuff->nb_chars += strlen (dirent->d_name) + 1;
01265 rep.stuff->nb_entries ++;
01266 }
01267 qsort (rep.stuff->entries, rep.stuff->nb_entries,
01268 sizeof * rep.stuff->entries, bx_compare_filenames);
01269 return rep;
01270 }
01271
01272 #define BX_MAX_BUF 2048
01273
01274 bx_dir
01275 bx_open_dir_f (char format [], ...)
01276 {
01277 char buffer [BX_MAX_BUF];
01278 va_list args;
01279 va_start (args, format);
01280 vsprintf (buffer, format, args);
01281 va_end (args);
01282 return bx_open_dir_f (buffer);
01283 }
01284
01285 #undef BX_MAX_BUF
01286
01287 void
01288 bx_close_dir (bx_dir dir)
01289 {
01290 free (dir.stuff);
01291 }
01292
01293 int
01294 bx_dir_length (bx_dir dir)
01295 {
01296 return dir.stuff->nb_entries;
01297 }
01298
01299 char *
01300 bx_dir_filename (bx_dir dir, int index)
01301 {
01302 return dir.stuff->entries [index];
01303 }
01304
01305
01306
01307
01308
01309
01310 #ifdef BX_AUDIO
01311
01312 struct bx_audio_stuff {
01313 SDL_AudioSpec file_spec;
01314 Uint8 * unconverted_buffer;
01315 Uint32 unconverted_length;
01316
01317
01318 SDL_AudioCVT converter;
01319 };
01320
01321 typedef struct Track {
01322 bx_audio sound;
01323 int index;
01324 int die_at;
01325 double volume;
01326 unsigned long start_date;
01327 int has_started;
01328 } Track;
01329
01330 #define MAX_TRACKS 20
01331 static int nb_tracks;
01332 static Track tracks [MAX_TRACKS];
01333
01334 #define AUDIO_BUFFER_SIZE 1024
01335 static SDL_AudioSpec spec_desired;
01336 static SDL_AudioSpec spec_obtained;
01337
01338 static void MyAudioFiller (void * data, Uint8 * stream, int length);
01339 static void MyAudioFiller_Aux (int num_track, Uint8 * stream, int length);
01340
01341 void
01342 bx_init_audio (void)
01343 {
01344 spec_desired.freq = 22050;
01345 spec_desired.format = AUDIO_S16;
01346 spec_desired.channels = 2;
01347 spec_desired.samples = AUDIO_BUFFER_SIZE;
01348 spec_desired.callback = MyAudioFiller;
01349 spec_desired.userdata = NULL;
01350
01351 if (SDL_OpenAudio (& spec_desired, & spec_obtained) < 0 )
01352 {
01353 fprintf(stderr, "bx_init_audio() with SDL failed: %s\n", SDL_GetError());
01354 exit (1);
01355 }
01356 nb_tracks= 0;
01357 }
01358
01359 bx_audio
01360 bx_load_audio (char filename [])
01361 {
01362 bx_audio audio;
01363
01364 audio.stuff= malloc (sizeof * audio.stuff);
01365 if(! SDL_LoadWAV (filename,
01366 & audio.stuff->file_spec,
01367 & audio.stuff->unconverted_buffer,
01368 & audio.stuff->unconverted_length))
01369 {
01370 printf("bx_load_audio() failed with file file %s: %s\n",
01371 filename, SDL_GetError ());
01372 exit (1);
01373 }
01374 SDL_BuildAudioCVT (& audio.stuff->converter,
01375 audio.stuff->file_spec.format,
01376 audio.stuff->file_spec.channels,
01377 audio.stuff->file_spec.freq,
01378 spec_obtained.format,
01379 spec_obtained.channels,
01380 spec_obtained.freq);
01381
01382 audio.stuff->converter.buf = malloc (audio.stuff->unconverted_length *
01383 audio.stuff->converter.len_mult);
01384
01385 audio.stuff->converter.len = audio.stuff->unconverted_length;
01386
01387 memcpy (audio.stuff->converter.buf,
01388 audio.stuff->unconverted_buffer,
01389 audio.stuff->unconverted_length);
01390 SDL_ConvertAudio (& audio.stuff->converter);
01391
01392 return audio;
01393 }
01394
01395
01396 #define BX_MAX_BUF 2048
01397
01398 bx_audio
01399 bx_load_audio_f (char format [], ...)
01400 {
01401 char buffer [BX_MAX_BUF];
01402 va_list args;
01403 va_start (args, format);
01404 vsprintf (buffer, format, args);
01405 va_end (args);
01406 return bx_load_audio (buffer);
01407 }
01408
01409 #undef BX_MAX_BUF
01410
01411 void
01412 bx_play_audio (bx_audio audio, double volume,
01413 unsigned long millisec, int ad_infinitum)
01414 {
01415 struct timeval now;
01416
01417 if (nb_tracks >= MAX_TRACKS)
01418 return;
01419 tracks[nb_tracks].sound= audio;
01420 tracks[nb_tracks].index= 0;
01421 tracks[nb_tracks].volume= volume;
01422 tracks[nb_tracks].die_at= ad_infinitum ? -1 : audio.stuff->converter.len_cvt;
01423
01424 gettimeofday (& now, NULL);
01425
01426 tracks[nb_tracks].start_date= now.tv_sec * 1000UL + now.tv_usec / 1000UL;
01427 tracks[nb_tracks].start_date += millisec;
01428 tracks[nb_tracks].has_started= 0;
01429 nb_tracks ++;
01430 SDL_PauseAudio(0);
01431 }
01432
01433 static void
01434 MyAudioFiller (void * data UNUSED, Uint8 * stream, int length)
01435 {
01436 struct timeval now;
01437 ULong date;
01438 int k;
01439 gettimeofday (& now, NULL);
01440
01441 date= now.tv_sec * 1000UL + now.tv_usec / 1000UL;
01442 memset (stream, 0, length);
01443 for (k= 0; k < nb_tracks; k++) {
01444 if (tracks [k].start_date <= date) {
01445 tracks [k].has_started= 1;
01446 MyAudioFiller_Aux (k, stream, length);
01447 }
01448 }
01449 }
01450
01451 void
01452 MyAudioFiller_Aux (int k, Uint8 * stream, int length)
01453 {
01454
01455 if (tracks[k].die_at != -1 &&
01456 length >= tracks[k].die_at) {
01457 length= tracks[k].die_at;
01458 }
01459 if (tracks[k].index + length >=
01460 tracks[k].sound.stuff->converter.len_cvt) {
01461 length = tracks[k].sound.stuff->converter.len_cvt - tracks [k].index;
01462 }
01463
01464 SDL_MixAudio (stream,
01465 tracks[k].sound.stuff->converter.buf +
01466 tracks[k].index,
01467 length,
01468 tracks[k].volume * SDL_MIX_MAXVOLUME);
01469
01470
01471 tracks[k].index += length;
01472 if (tracks[k].die_at != -1) {
01473 tracks[k].die_at -= length;
01474 }
01475
01476 if (tracks[k].index < tracks[k].sound.stuff->converter.len_cvt &&
01477 tracks[k].die_at != 0) {
01478
01479 return;
01480 }
01481
01482
01483
01484 if (tracks[k].die_at == -1) {
01485
01486 tracks[k].index= 0;
01487 return;
01488 }
01489
01490
01491 if (k != nb_tracks - 1) {
01492 tracks [k]= tracks [nb_tracks - 1];
01493 }
01494 nb_tracks--;
01495 }
01496
01497 #endif
01498
01499 #ifdef MAIN
01500 int main(void) {
01501 bx_window window;
01502 bx_init ();
01503 window= bx_create_window ("bx test", 10, 10, 100, 100);
01504 bx_loop ();
01505 return 0;
01506 }
01507 #endif