#!/bin/ksh # # CD Player frontend for CDDA2WAV # # Programmed during the rainy feb 12, 2005 # (c) Peter van Eerten - free for all use # # Runs with GTK-server 2.2.1 or higher. # # 1.0: Initial release # 1.1: Fixes for CDDA2WAV on OpenBSD (june 1 2005) # 1.2: Now combobox synchronizes with track (june 4 2005) # 1.2a: Fixes for CD's with more than 10 tracks (september 9, 2005) # 1.3: -Removed ' character from titles (october 18, 2005) # -Support for intern. characters (october 18, 2005) # 1.4: -Revised for async event handling (june 18, 2006) # -Window does not resize when track titles have large size (june 18, 2006) # 1.5: -Major code improvements (july 22, 2008) #------------------------------------------------------------------------------------- # # Minimalistic frontend to play audio CD's over PCM # # Required tools: # -cdda2wav # -GNU Awk # -rexima OR aumix # -...and of course coreutils like 'cat' and 'tr'. # #------------------------------------------------ CHECK function Check_Software { # Check on availability of AWK AWK=`which gawk 2>/dev/null` if [[ -z $AWK ]] then echo "GNU Awk not found on your system! Exiting..." exit 1 fi # Check on availability of REXIMA or AUMIX MIXER=`which rexima 2>/dev/null` if [[ -z $MIXER || $MIXER = "rexima: Command not found." ]] then MIXER=`which aumix 2>/dev/null` if [[ -z $MIXER || $MIXER = "aumix: Command not found." ]] then echo "No mixer found! Exiting..." exit 1 fi fi # Check on availability of cdda2wav CDDA2WAV=`which cdda2wav 2>/dev/null` if [[ -z $CDDA2WAV ]] then echo "cdda2wav not found on your system! Exiting..." exit 1 fi } CDPARANOIA=`which cdparanoia >/dev/null` #------------------------------------------------ GTK # Communication function; $1 contains the string to be send function gtk { print -p $1 read -p RESULT } #------------------------------------------------ GUI function Build_Gui { # Start GTK-server in STDIN mode gtk-server -stdin |& # Check GTK version gtk "gtk_check_version 2 4 0" if [[ -n $RESULT ]] then echo "Your GTK installation is too old!" echo "GTK version 2.4.0 or higher is required. Exiting..." gtk "gtk_server_exit" exit 1 fi # Define GUI - mainwindow gtk "gtk_init NULL NULL" gtk "gtk_window_new 0" WINDOW=$RESULT gtk "gtk_window_set_title $WINDOW 'CD Player 1.5'" gtk "gtk_window_set_position $WINDOW 1" #gtk "gtk_widget_set_size_request $WINDOW 350 60" # Register timeout in WAIT callback later gtk "gtk_server_connect $WINDOW show main_window" gtk "gtk_server_timeout 500 $WINDOW show" # Buttons gtk "gtk_button_new_from_stock gtk-stop" G_BUTTON_STOP=$RESULT gtk "gtk_button_new_from_stock gtk-refresh" G_BUTTON_REFRESH=$RESULT gtk "gtk_button_new_from_stock gtk-quit" G_BUTTON_QUIT=$RESULT gtk "gtk_button_new_from_stock gtk-help" G_BUTTON_HELP=$RESULT # Volume slider gtk "gtk_vscale_new_with_range 0 100 1" G_VOLUME=$RESULT gtk "gtk_scale_set_draw_value $G_VOLUME 0" gtk "gtk_range_set_value $G_VOLUME 25" # Combobox with titles of CD gtk "gtk_combo_box_new_text" G_COMBO=$RESULT # Create layout gtk "gtk_hbox_new 0 0" H1BOX=$RESULT gtk "gtk_box_pack_start $H1BOX $G_BUTTON_STOP 1 1 1" gtk "gtk_box_pack_start $H1BOX $G_BUTTON_REFRESH 1 1 1" gtk "gtk_box_pack_start $H1BOX $G_BUTTON_HELP 1 1 1" gtk "gtk_box_pack_end $H1BOX $G_BUTTON_QUIT 1 1 1" gtk "gtk_vbox_new 0 0" VBOX=$RESULT gtk "gtk_box_pack_start $VBOX $H1BOX 1 1 1" gtk "gtk_box_pack_start $VBOX $G_COMBO 1 1 1" gtk "gtk_hbox_new 0 0" HTOPBOX=$RESULT gtk "gtk_box_pack_start $HTOPBOX $VBOX 1 1 1" gtk "gtk_box_pack_start $HTOPBOX $G_VOLUME 0 0 0" gtk "gtk_container_add $WINDOW $HTOPBOX" gtk "gtk_widget_show_all $WINDOW" # Create ABOUT box gtk "gtk_server_version" TMP="\t*** A simple CD player for XFCE ***\r\rProgrammed with KSH and GTK-server $RESULT.\r\r Visit http://www.gtk-server.org/ for more info!" gtk "gtk_message_dialog_new $WINDOW 0 0 2 '$TMP' ''" ABOUT=$RESULT gtk "gtk_window_set_title $ABOUT 'About CD Player 1.5'" } #------------------------------------------------ CDLOOKUP function Lookup_CD { # Kill existing playing process first Stop_CD # First remove existing tracks from widget if [[ $TRACKS -gt 0 ]] then COUNTER=0 until [[ $COUNTER -eq $TRACKS ]] do gtk "gtk_combo_box_remove_text $G_COMBO 0" ((COUNTER+=1)) done fi # Check availability of CD if [[ -n $CDPARANOIA ]] then CHECK=`$CDPARANOIA -Q 2>&1` if [[ $CHECK = +(*004*) ]] then return fi fi # Lookup information from CDDB $CDDA2WAV -D $CDROM -J -v titles -L 1 -N -H 2>&1 | tr -d "'" | $AWK '/Album/ {print} /Track/ {print}' > $CDFILE # Determine amount of tracks (includes album title) TRACKS=`$AWK 'BEGIN {t = 0} /Track/ {t+=1} END {print t}' $CDFILE` # If no tracks then reread CD if [[ $TRACKS -lt 1 ]] then # Restore default title gtk "gtk_window_set_title $WINDOW 'Unknown album'" # Get physical track index $CDDA2WAV -D $CDROM -J -v toc -N -H -g 2>&1 | tr -d "'" > $CDFILE # Determine amount of tracks (includes album title) TRACKS=`$AWK 'BEGIN {t = 0} /T[0-9]/ {t+=1} END {print t}' $CDFILE` # Add track numbering to combobox COUNTER=1 until [[ $COUNTER -gt $TRACKS ]] do gtk "gtk_combo_box_append_text $G_COMBO '$COUNTER - Unknown track'" ((COUNTER+=1)) done else # Add CD title to window title L_TITLE=`$AWK '/Album/ {print}' $CDFILE` gtk "gtk_window_set_title $WINDOW '$L_TITLE'" # Add tracks to combobox COUNTER=1 while read LINE do if [[ $LINE == +(*Track*) ]] then gtk "g_locale_to_utf8 '$LINE' -1 NULL NULL NULL" gtk "gtk_combo_box_append_text $G_COMBO '$RESULT'" fi done < $CDFILE fi } #------------------------------------------------ STOP function Stop_CD { # Only if PID exists, kill process if [[ -n $P_PID ]] then STOPPED=1 kill -9 $P_PID >/dev/null 2>&1 P_PID="" fi } #------------------------------------------------ PLAY function Play_CD { # Get selected track from combo gtk "gtk_combo_box_get_active $G_COMBO" let P_TRACK=$RESULT+1 # Kill existing playing process first Stop_CD # Start playing and save PID $CDDA2WAV -D $CDROM -q -e -t$P_TRACK -d0 -N >/dev/null 2>&1 & # Unset stopped flag STOPPED=0 # Save ProcessID P_PID=`jobs -p | head -1` } #------------------------------------------------ SELECT NEXT TRACK function Action_Track { # Find out if track currently is being played TMP=`jobs -l | grep $P_PID 2>/dev/null` # If not, and not stopped, goto next track if [[ -z $TMP && $STOPPED -eq 0 ]] then # Get selected track from combo gtk "gtk_combo_box_get_active $G_COMBO" let P_TRACK=$RESULT+1 # Put to next track if [[ $P_TRACK -lt $TRACKS ]] then # Put combobox to next track, inducing signal gtk "gtk_combo_box_set_active $G_COMBO $P_TRACK" fi fi } #------------------------------------------------ VOLUME function Adjust_Volume { # Get current value gtk "gtk_range_get_value $G_VOLUME" let V_VOL=100-`$AWK -v VAR=$RESULT 'BEGIN {print int(VAR)}'` case $MIXER in `which rexima 2>/dev/null`) $MIXER pcm $V_VOL;; `which aumix 2>/dev/null`) $MIXER -v $V_VOL;; esac } #------------------------------------------------ MAIN # Set global variables CDROM=/dev/cdrom CDFILE=/tmp/CD.txt # Check available packages Check_Software # Create GUI Build_Gui # Get CD info Lookup_CD # Put volume to default Adjust_Volume # Initialize variables EVENT=0 # Mainloop while [[ $EVENT -ne $WINDOW && $EVENT -ne $G_BUTTON_QUIT ]] do # Wait for event gtk "gtk_server_callback wait" EVENT=$RESULT # Check events case $EVENT in # If refresh button is pressed $G_BUTTON_REFRESH) Lookup_CD;; # If help button is pressed $G_BUTTON_HELP) gtk "gtk_widget_show $ABOUT";; # If OK button in HELP dialog is pressed $ABOUT) gtk "gtk_widget_hide $ABOUT";; # If stop button is pressed $G_BUTTON_STOP) Stop_CD;; # If volume slider is moved $G_VOLUME) Adjust_Volume;; # If combobox is changed $G_COMBO) Play_CD;; esac # Check if we need to go to next track Action_Track done # Before exiting, stop playing CD Stop_CD # Remove temporary file rm -f $CDFILE # Exit GTK gtk "gtk_server_exit"