#!/usr/bin/newlisp #------------------------------------------------------- # # The Mouse O'meter: another artistic contribution to # the realm of useless programs - but fun! # # Run with GTK-server 2.0.11 or higher and newLisp 10 or higher. # # Tested with GTK 2 on Slackware Linux 10 and on Windows2000. # # Dec 19, 2004 - PvE. # #------------------------------------------------------- # Version 1.0 # - Initial release # # Version 1.1 (july 1, 2006) # - Code improvements # - Use async # - Switched to embedded GTK :-) # # Version 1.2 (december 2008) # - Compliant with newLisp 10 # - Small code improvements #------------------------------------------------------- # Import GTK-server for Unix or Windows and create global symbols for GTK function names (case ostype ("Win32" (import "gtk-server.dll" "gtk")) ("OSX" (import "libgtk-server.dylib" "gtk")) (true (import "libgtk-server.so" "gtk"))) # Now try to find GTK-server configfile (set 'cfgfile (open "gtk-server.cfg" "read")) (when (not cfgfile) (set 'cfgfile (open "/usr/local/etc/gtk-server.cfg" "read")) (when (not cfgfile) (set 'cfgfile (open "/etc/gtk-server.cfg" "read")))) # No configfile? Exit (when (not cfgfile)(println "No GTK-server configfile found! Exiting...")(exit)) # Create global GTK symbols (while (read-line cfgfile) (when (and (starts-with (current-line) "FUNCTION_NAME") (regex "gtk_+|gdk_+|g_+" (current-line))) (set 'func (chop ((parse (current-line) " ") 2))) (set 'lb (append {(lambda()(setq s "} func {")(dolist (x (args))(setq s (string s " " x)))(get-string (gtk s)))})) (constant (global (sym func)) (eval-string lb)))) (close cfgfile) (constant (global 'NULL) "NULL") (set-locale "C") #--------------------------------------------------------------------------------------- GUI # # GUI definition # (context 'GUI) # Setup main window #(gtk_server_cfg "-log=log.txt") (gtk_init "NULL" "NULL") (set 'win (gtk_window_new 0)) (gtk_window_set_title win {"Mouse O'meter"}) (gtk_widget_set_usize win 200 40) (gtk_window_set_position win 1) (gtk_window_set_resizable win 0) (gtk_window_set_icon_name win "mouse") (gtk_window_set_keep_above win 1) # Prepare async (gtk_server_connect win "show win") (gtk_server_timeout 75 win "show") # The labels (set 'dlabel (gtk_label_new {"Distance: 0.00 meters."})) (set 'slabel (gtk_label_new {"Average speed: 0.00 cm/s."})) # Now arrange widgets on window using boxes (set 'vbox (gtk_vbox_new 0 0)) (gtk_box_pack_start vbox dlabel 0 0 1) (gtk_box_pack_start vbox slabel 0 0 1) (gtk_container_add win vbox) # Show all widgets (gtk_widget_show_all win) # Set text in label (define (text_label widget txt) (gtk_label_set_text widget (append {"} txt {"})) ) #------------------------------------------------------- # # Main program # (context 'MAIN) # Put to your monitorsize - value in inches (constant 'monitor_size 17) # Put to 1 if you are American and want to see inches - 2.54 is for centimeters (constant 'inch_factor 2.54) # Put this to a lower value for better accuracy but higher CPU load (constant 'delay 50) #------------------------------------------------------- # Initialize screen (define (gdk_initialize) (gdk_init NULL NULL) (set 'display (gdk_display_get_default)) (when (= display 0) (println "ERROR: Could not open display!") (exit) ) ) #------------------------------------------------------- # Find centimetersize of 1 pixel (define (get_factor) # First, find diagonal actual resolution (set 'xres (int (gdk_screen_width))) (set 'yres (int (gdk_screen_height))) # Our friend Pythagoras does the trick (set 'diag_res (sqrt (+ (pow xres)(pow yres)))) # Now calculate pixelsize to centimeters based on 17inch monitor (set 'cm_factor (mul (div monitor_size diag_res) inch_factor)) ) #------------------------------------------------------- # Find relative coordinates (define (relative_mouse) # Reserve memory for x and y (set 'x (dup "\000" 10)) (set 'y (dup "\000" 10)) (gdk_display_get_pointer display NULL (address x) (address y) 0) (if (= curx nil) (begin (set 'dx 0) (set 'dy 0)) (begin (set 'dx (abs (- curx (get-int x)))) (set 'dy (abs (- cury (get-int y)))))) (set 'curx (get-int x)) (set 'cury (get-int y)) ) #------------------------------------------------------- # Setup (gdk_initialize) (get_factor) # Initialize vars (set 'distance 0) # Notify starting time (set 'start_time (apply date-value (now))) # Mainloop (do-until (= event GUI:win) # Get event (set 'event (gtk_server_callback "wait")) # Find relative coordinates (relative_mouse) # Calculate total pixel distance using Pythagoras (set 'distance (add (sqrt (+ (pow dx)(pow dy))) distance)) # Calculate distance in meters (set 'result (div (mul cm_factor distance) 100)) # Put onto label (GUI:text_label GUI:dlabel (append "Distance: " (format "%6.2f" result) " meters.")) # Calculate speed (setq time_len (- (apply date-value (now)) start_time)) (if (> time_len 0) (GUI:text_label GUI:slabel (append "Average speed: " (format "%6.2f" (div (mul cm_factor distance) time_len)) " cm/s."))) ) # Exit newlisp (exit)