#!/bin/ksh # # KSH script using the GTK-server to tune a radiocard. # Tested with GTK2.x on Zenwalk Linux 4.8 # # *** Does NOT work with GTK 1.x.!!! *** # # This is version 3 of my radiocard tuner GUI. I am actually # using this script to tune my ISA Aztech/Packardbell radiocard # in my 2nd computer! # # -3.0: added extra functionality # -3.1: fixed bug with changing/muting volume (25/02/2004) # -3.2: -no rc file is needed to set color (22/11/2005) # -spaces can be used in preset names (22/11/2005) # -overall code improvements (22/11/2005) # -about box changed message (23/11/2005) # -show icon in window (24/11/2005) # -3.3: -new preset functionality (1/9/2006) # -works with PDKSH now (9/9/2006) # -3.4: -changed to embedded GTK (7/10/2006) # -3.5: -interface changed (25/2/2007) # -reordering of channels is possible now (25/2/2007) # -fixed bug with deleting a preset channel (25/2/2007) # -entry always keeps focus (25/2/2007) # -fixed bug with MUTE mode (25/2/2007) # -abandoned AWK (25/2/2007) # -ABOUT dialog has title now (25/2/2007) # -3.6: -added tooltips for the buttons (7/10/2007) # -3.7: -adapted for GTK-server 2.2.3 and higher (26/3/2008) # -improved embedded GTK header routine (26/3/2008) # -warnings are graphical now (26/3/2008) # -3.8: -fixed mixer tuning on FM card (8/8/2009) # -removed autofocus to entry (8/8/2009) # # Additional software: # -fmtools for tuning (http://www.exploits.org/v4l/fmtools/ # or http://www.stanford.edu/~blp/fmtools/) # -optional: rexima or aumix for volume adjustment # # January 22, 2004 by Peter van Eerten - GPL license. # Changed for GTK-server 1.2 at October 10, 2004 # Changed for GTK-server 1.3 at December 6, 2004 # # This program should work with KornShell/PDKSH and GTK-server 2.1.x or newer. # ############################################################################ # Find GTK-server configfile first if [[ -f gtk-server.cfg ]]; then CFG=gtk-server.cfg elif [[ -f /etc/gtk-server.cfg ]]; then CFG=/etc/gtk-server.cfg elif [[ -f /usr/local/etc/gtk-server.cfg ]]; then CFG=/usr/local/etc/gtk-server.cfg else echo "No GTK-server configfile found! Please install GTK-server..." exit 1 fi # Now create global functionnames from GTK API if [[ ! -f $HOME/.gtk4korn || $CFG -nt $HOME/.gtk4korn ]]; then print "# Embedded GTK functions for KornShell" > $HOME/.gtk4korn while read LINE do if [[ $LINE == +(*FUNCTION_NAME*) ]]; then TMP=${LINE#*= } print "function ${TMP%%,*}" >> $HOME/.gtk4korn print "{\nprint -p ${TMP%%,*} \$@" >> $HOME/.gtk4korn print "read -p GTK\n}" >> $HOME/.gtk4korn fi done < $CFG fi # Declare global variables typeset GTK NULL="NULL" unset CFG PIPE LINE # Include embedded GTK for KornShell . $HOME/.gtk4korn ############################################## function Check_Software { # Check on availability of fmtools FM=`which fm 2>/dev/null` if [[ -z $FM ]] then gtk_message_dialog_new $NULL 0 3 2 "'\nThe fmtools were not found on your system!\n\nPlease download the latest version from:\n\nhttp://www.stanford.edu/~blp/fmtools/'" "''" WD=$GTK gtk_window_set_title $WD "'Error'" # Set icon if [[ -f "$MYDIR/mini-radio.xpm" ]] then gtk_window_set_icon_from_file $WD "'$MYDIR/mini-radio.xpm'" NULL fi gtk_widget_show_all $WD while [[ $GTK -ne $WD ]] do gtk_server_callback "wait" done gtk_widget_hide $WD gtk_exit 0 exit 1 fi # Check on availability of REXIMA or AUMIX MIXER=`which rexima 2>/dev/null` if [[ -z $MIXER ]] then MIXER=`which aumix 2>/dev/null` if [[ -z $MIXER ]] then gtk_message_dialog_new $NULL 0 1 2 "'\nNo mixer found! The volume will be set on your radiocard.'" "''" WD=$GTK gtk_window_set_title $WD "'Warning'" # Set icon if [[ -f "$MYDIR/mini-radio.xpm" ]] then gtk_window_set_icon_from_file $WD "'$MYDIR/mini-radio.xpm'" NULL fi gtk_widget_show_all $WD while [[ $GTK -ne $WD ]] do gtk_server_callback "wait" done gtk_widget_hide $WD fi fi # Go back return } ############################################## function Build_Gui { # Check GTK version gtk_check_version 2 4 0 if [[ -n $GTK ]] then gtk_message_dialog_new $NULL 0 3 2 "'\n\tYour GTK installation is too old!\n\nGTK version 2.4.0 or higher is required. Exiting...'" "''" WD=$GTK gtk_window_set_title $WD "'Error'" # Set icon if [[ -f "$MYDIR/mini-radio.xpm" ]] then gtk_window_set_icon_from_file $WD "'$MYDIR/mini-radio.xpm'" NULL fi gtk_widget_show_all $WD while [[ $GTK -ne $WD ]] do gtk_server_callback "wait" done gtk_widget_hide $WD gtk_exit 0 exit 1 fi # Main window gtk_window_new 0 WINDOW=$GTK gtk_window_set_title $WINDOW "'KSH Radio Tuner'" gtk_window_set_position $WINDOW 1 gtk_widget_set_size_request $WINDOW 350 230 gtk_window_set_resizable $WINDOW 0 gtk_table_new 50 55 1 TABLE=$GTK gtk_container_add $WINDOW $TABLE # Set icon if [[ -f "$MYDIR/mini-radio.xpm" ]] then gtk_window_set_icon_from_file $WINDOW "'$MYDIR/mini-radio.xpm'" NULL fi # Create ABOUT box gtk_server_version TMP="\t*** KSH Radio Controller ***\r\rProgrammed with KSH and GTK-server $GTK.\r\r Visit http://www.gtk-server.org/ for more info!" gtk_message_dialog_new $WINDOW 0 0 2 "'$TMP'" "''" DIALOG=$GTK gtk_window_set_title $DIALOG "'About the KSH Radio tuner'" # Buttons gtk_button_new ABOUT_BUTTON=$GTK gtk_image_new_from_stock "gtk-about" 4 ABOUT_IMAGE=$GTK gtk_table_attach_defaults $TABLE $ABOUT_BUTTON 38 45 42 48 gtk_container_add $ABOUT_BUTTON $ABOUT_IMAGE gtk_tooltips_new ABOUT_TIPS=$GTK gtk_tooltips_set_tip $ABOUT_TIPS $ABOUT_BUTTON "'Show credits'" "''" gtk_button_new EXIT_BUTTON=$GTK gtk_image_new_from_stock "gtk-quit" 4 EXIT_IMAGE=$GTK gtk_table_attach_defaults $TABLE $EXIT_BUTTON 46 53 42 48 gtk_container_add $EXIT_BUTTON $EXIT_IMAGE gtk_tooltips_new EXIT_TIPS=$GTK gtk_tooltips_set_tip $EXIT_TIPS $EXIT_BUTTON "'Click to exit'" "''" # Frequency scale gtk_hscale_new_with_range 87.5 108.0 0.1 FREQSCALE=$GTK gtk_table_attach_defaults $TABLE $FREQSCALE 2 34 7 16 gtk_scale_set_draw_value $FREQSCALE 1 gtk_tooltips_new FREQ_TIPS=$GTK gtk_tooltips_set_tip $FREQ_TIPS $FREQSCALE "'Move slider to tune the radio'" "''" gtk_label_new "'Audio: '" gtk_frame_new $NULL TUNE_FRAME=$GTK gtk_table_attach_defaults $TABLE $TUNE_FRAME 1 35 1 18 gtk_frame_set_label $TUNE_FRAME "' Radio Card Tuning '" # Volume scale gtk_hscale_new_with_range 0 100 1 VOLSCALE=$GTK gtk_table_attach_defaults $TABLE $VOLSCALE 37 53 7 16 gtk_scale_set_draw_value $VOLSCALE 1 gtk_range_set_value $VOLSCALE 70 gtk_tooltips_new VOL_TIPS=$GTK gtk_tooltips_set_tip $VOL_TIPS $VOLSCALE "'Move slider to set the volume'" "''" gtk_frame_new $NULL VOLUME_FRAME=$GTK gtk_table_attach_defaults $TABLE $VOLUME_FRAME 36 54 1 18 gtk_frame_set_label $VOLUME_FRAME "' Volume '" # Preset label and entry gtk_label_new "'Preset: '" LABEL1=$GTK gtk_table_attach_defaults $TABLE $LABEL1 33 40 27 30 gtk_misc_set_alignment $LABEL1 1.0 0.5 gtk_entry_new ENTRY=$GTK gtk_table_attach_defaults $TABLE $ENTRY 40 53 27 30 gtk_tooltips_new ENTRY_TIPS=$GTK gtk_tooltips_set_tip $ENTRY_TIPS $ENTRY "'Fill in and press to add preset'" "''" gtk_label_new "'Audio: '" LABEL2=$GTK gtk_table_attach_defaults $TABLE $LABEL2 33 40 32 37 gtk_misc_set_alignment $LABEL2 1.0 0.5 gtk_toggle_button_new_with_label "Mute" MUTE_BUTTON=$GTK gtk_table_attach_defaults $TABLE $MUTE_BUTTON 40 53 32 37 gtk_tooltips_new MUTE_TIPS=$GTK gtk_tooltips_set_tip $MUTE_TIPS $MUTE_BUTTON "'Mute/unmute sound'" "''" gtk_button_new DEL_BUTTON=$GTK gtk_image_new_from_stock "gtk-delete" 4 DEL_IMAGE=$GTK gtk_table_attach_defaults $TABLE $DEL_BUTTON 24 29 33 38 gtk_container_add $DEL_BUTTON $DEL_IMAGE gtk_tooltips_new DEL_TIPS=$GTK gtk_tooltips_set_tip $DEL_TIPS $DEL_BUTTON "'Delete selected preset'" "''" gtk_button_new UP_BUTTON=$GTK gtk_image_new_from_stock "gtk-go-up" 4 UP_IMAGE=$GTK gtk_table_attach_defaults $TABLE $UP_BUTTON 24 29 24 29 gtk_container_add $UP_BUTTON $UP_IMAGE gtk_tooltips_new UP_TIPS=$GTK gtk_tooltips_set_tip $UP_TIPS $UP_BUTTON "'Move selected preset up'" "''" gtk_button_new DOWN_BUTTON=$GTK gtk_image_new_from_stock "gtk-go-down" 4 DOWN_IMAGE=$GTK gtk_table_attach_defaults $TABLE $DOWN_BUTTON 24 29 42 47 gtk_container_add $DOWN_BUTTON $DOWN_IMAGE gtk_tooltips_new DOWN_TIPS=$GTK gtk_tooltips_set_tip $DOWN_TIPS $DOWN_BUTTON "'Move selected preset down'" "''" gtk_frame_new $NULL CONFIG_FRAME=$GTK gtk_table_attach_defaults $TABLE $CONFIG_FRAME 31 54 19 49 gtk_frame_set_label $CONFIG_FRAME "' Control Panel '" # List of presets gtk_frame_new $NULL ITER=$GTK gtk_list_store_new 1 64 LST=$GTK gtk_tree_view_new_with_model $LST CHOICE=$GTK gtk_server_connect $CHOICE button-press-event $CHOICE 1 gtk_tree_view_set_headers_visible $CHOICE 0 gtk_tree_view_get_selection $CHOICE SEL=$GTK gtk_cell_renderer_text_new CELL=$GTK gtk_tree_view_column_new_with_attributes Instance $CELL text 0 NULL COLUMN=$GTK gtk_tree_view_append_column $CHOICE $COLUMN gtk_tree_view_column_set_resizable $COLUMN 1 gtk_tree_view_column_set_clickable $COLUMN 1 gtk_scrolled_window_new $NULL $NULL SW=$GTK gtk_scrolled_window_set_placement $SW 2 gtk_scrolled_window_set_policy $SW 1 1 gtk_scrolled_window_set_shadow_type $SW 1 gtk_container_add $SW $CHOICE gtk_table_attach_defaults $TABLE $SW 2 23 24 47 if [[ -f $HOME/.kshradio ]] then NR=0 while read LINE do if [[ $LINE == +(*channel*) ]] then TMP=${LINE#* } FREQ[$NR]=${TMP%% *} TMP=${TMP#* } CHAN[$NR]=${TMP% * } fi if [[ ${CHAN[$NR]} != "" ]] then gtk_list_store_append $LST $ITER gtk_list_store_set $LST $ITER 0 "'${CHAN[$NR]}'" -1 ((NR+=1)) fi done < $HOME/.kshradio UBOUND=$NR fi gtk_frame_new $NULL PRESET_FRAME=$GTK gtk_table_attach_defaults $TABLE $PRESET_FRAME 1 30 19 49 gtk_frame_set_label $PRESET_FRAME "' Channels '" # Show it all! gtk_widget_show_all $WINDOW gtk_widget_grab_focus $ENTRY return } ############################################## function Set_Volume { # $1 contains the mixer, $2 contains the volume, $3 contains frequency case $1 in `which rexima 2>/dev/null`) $1 line $2;; `which aumix 2>/dev/null`) $1 -l $2;; *) fm $2 $1*655;; esac } ############################################## # Initialize environment export LC_ALL=nl_NL export LD_LIBRARY_PATH=/usr/X11R6/lib # Start GTK-server gtk-server stdin |& # Save my directory MYDIR=${0%/*} # Check available packages on system gtk_init $NULL $NULL Check_Software # Read saved settings if available if [[ -f $HOME/.kshradio ]] then while read LINE do if [[ $LINE == +(*volume*) ]]; then VOLUME=${LINE#* }; fi if [[ $LINE == +(*frequency*) ]]; then CURFREQ=${LINE#* }; fi done < $HOME/.kshradio else VOLUME=70 CURFREQ=87.5 fi # Create user interface Build_Gui # Adjust widgets accordingly gtk_range_set_value $VOLSCALE $VOLUME gtk_range_set_value $FREQSCALE $CURFREQ NR=0 while [[ $NR -lt $UBOUND ]] do if [[ $CURFREQ = ${FREQ[$NR]} ]] then gtk_tree_path_new_from_string $NR PTH=$GTK gtk_tree_selection_select_path $SEL $PTH gtk_tree_view_scroll_to_cell $CHOICE $PTH $COLUMN 0 0.0 0.0 gtk_tree_path_free $PTH break else ((NR+=1)) fi done # Set the volume and frequency Set_Volume $MIXER $VOLUME $CURFREQ fm $CURFREQ 65535 > /dev/null # Initialize EVENT=0 MUTE=1 MODE=0 # This is the mainloop while [[ $EVENT -ne $EXIT_BUTTON && $EVENT -ne $WINDOW ]] do # Walk through all GTK events gtk_server_callback "wait" EVENT=$GTK case $EVENT in # Mute/unmute the radiocard $MUTE_BUTTON) let MUTE=1-$MUTE if [[ $MUTE -eq 0 ]] then gtk_button_set_label $MUTE_BUTTON "Unmute" else gtk_button_set_label $MUTE_BUTTON "Mute" fi;; # Set the volume $VOLSCALE) gtk_range_get_value $VOLSCALE VOLUME=${GTK%.*} # Set the volume Set_Volume $MIXER $VOLUME $CURFREQ # Slider changed, put radio on if it was muted fm $CURFREQ 65535 > /dev/null # Radio not muted anymore MUTE=1 gtk_button_set_label $MUTE_BUTTON "Mute";; # Set the radiofrequency $FREQSCALE) gtk_range_get_value $FREQSCALE CURFREQ=$GTK fm $CURFREQ 65535 > /dev/null;; # Check the ABOUT button $ABOUT_BUTTON) gtk_widget_show $DIALOG;; # Check if the dialog was closed $DIALOG) gtk_widget_hide $DIALOG;; # Set preset channel $ENTRY) gtk_entry_get_text $ENTRY TXT=$GTK if [[ $TXT != "" ]] then CHAN[$UBOUND]=$TXT gtk_list_store_append $LST $ITER gtk_list_store_set $LST $ITER 0 "'$TXT'" -1 FREQ[$UBOUND]=$CURFREQ ((UBOUND+=1)) gtk_editable_delete_text $ENTRY 0 -1 fi;; # Delete preset $DEL_BUTTON) NR=0 while [[ $NR -lt $UBOUND ]] do gtk_tree_path_new_from_string $NR PTH=$GTK gtk_tree_selection_path_is_selected $SEL $PTH ROW=$GTK if [[ $ROW = "1" ]] then break else gtk_tree_path_free $PTH ((NR+=1)) fi done if [[ $ROW = "1" ]] then gtk_tree_model_get_iter $LST $ITER $PTH gtk_list_store_remove $LST $ITER gtk_tree_path_free $PTH while [[ $NR -lt $UBOUND ]] do CHAN[$NR]=${CHAN[$NR+1]} FREQ[$NR]=${FREQ[$NR+1]} ((NR+=1)) done ((UBOUND-=1)) fi;; # Reorder preset up $UP_BUTTON) NR=0 while [[ $NR -lt $UBOUND ]] do gtk_tree_path_new_from_string $NR PTH=$GTK gtk_tree_selection_path_is_selected $SEL $PTH ROW=$GTK if [[ $ROW = "1" ]] then break else gtk_tree_path_free $PTH ((NR+=1)) fi done if [[ $ROW = "1" && $NR -gt 0 ]] then gtk_list_store_clear $LST let TMP=$NR-1 F_TMP=${FREQ[$TMP]} C_TMP=${CHAN[$TMP]} FREQ[$TMP]=${FREQ[$NR]} CHAN[$TMP]=${CHAN[$NR]} FREQ[$NR]=$F_TMP CHAN[$NR]=$C_TMP NR=0 while [[ $NR -lt $UBOUND ]] do gtk_list_store_append $LST $ITER gtk_list_store_set $LST $ITER 0 "'${CHAN[$NR]}'" -1 ((NR+=1)) done gtk_tree_path_prev $PTH gtk_tree_selection_select_path $SEL $PTH gtk_tree_view_scroll_to_cell $CHOICE $PTH $COLUMN 1 0.5 0.5 gtk_tree_path_free $PTH fi;; # Reorder preset down $DOWN_BUTTON) NR=0 while [[ $NR -lt $UBOUND ]] do gtk_tree_path_new_from_string $NR PTH=$GTK gtk_tree_selection_path_is_selected $SEL $PTH ROW=$GTK if [[ $ROW = "1" ]] then break else gtk_tree_path_free $PTH ((NR+=1)) fi done ((UBOUND-=1)) if [[ $ROW = "1" && $NR -lt $UBOUND ]] then ((UBOUND+=1)) gtk_list_store_clear $LST let TMP=$NR+1 F_TMP=${FREQ[$TMP]} C_TMP=${CHAN[$TMP]} FREQ[$TMP]=${FREQ[$NR]} CHAN[$TMP]=${CHAN[$NR]} FREQ[$NR]=$F_TMP CHAN[$NR]=$C_TMP NR=0 while [[ $NR -lt $UBOUND ]] do gtk_list_store_append $LST $ITER gtk_list_store_set $LST $ITER 0 "'${CHAN[$NR]}'" -1 ((NR+=1)) done gtk_tree_path_next $PTH gtk_tree_selection_select_path $SEL $PTH gtk_tree_view_scroll_to_cell $CHOICE $PTH $COLUMN 1 0.5 0.5 gtk_tree_path_free $PTH else ((UBOUND+=1)) fi;; # See if selection was clicked $CHOICE) NR=0 while [[ $NR -lt $UBOUND ]] do gtk_tree_path_new_from_string $NR PTH=$GTK gtk_tree_selection_path_is_selected $SEL $PTH ROW=$GTK gtk_tree_path_free $PTH if [[ $ROW = "1" ]] then fm ${FREQ[$NR]} 65535 > /dev/null gtk_range_set_value $FREQSCALE ${FREQ[$NR]} CURFREQ=${FREQ[$NR]} break else ((NR+=1)) fi done;; esac # Muted or not? if [[ $MUTE -eq 0 ]] then fm off > /dev/null else fm $CURFREQ 65535 > /dev/null fi # The entry should always keep focus #gtk_widget_grab_focus $ENTRY done # Remember last volume print "volume" $VOLUME> $HOME/.kshradio # Remember last frequency print "frequency" $CURFREQ>> $HOME/.kshradio # Remember preset channels NR=0 while [[ $NR -lt $UBOUND ]] do print "channel" ${FREQ[$NR]} ${CHAN[$NR]}>> $HOME/.kshradio ((NR+=1)) done # Mute radio at exit fm off > /dev/null # Exit GTK gtk_exit 0 # End exit 0