#!/bin/ksh
#
# CD Player frontend for CDDA2WAV
#
# Programmed during the rainy feb 12, 2005
# (c) Peter van Eerten - free for all use
#
# 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)
#-------------------------------------------------------------------------------------
#
# Minimalistic frontend to play audio CD's
#
# 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
}
# Check on availability of 'sleep'
SLEEP=`which sleep 2>/dev/null`
if [[ -z $SLEEP ]]
then
echo "GNU sleep not found on your system! High CPU load granted."
SLEEP=sleep
fi
#------------------------------------------------ GTK
# Communication function; $1 contains the string to be send
function gtk
{
print -p $1
read -p RESULT
}
#------------------------------------------------ GUI
function Build_Gui
{
# Setup environment for GTK server
#export LC_ALL=nl_NL
export LD_LIBRARY_PATH=/usr/X11R6/lib:/usr/lib:/usr/local/lib
# 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_exit 0"
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\""
gtk "gtk_window_set_position $WINDOW 1"
# 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 50"
# 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 $RESULT.\r\r Visit http://www.gtk-server.org/ for more info!"
gtk "gtk_message_dialog_new $WINDOW 0 0 2 \"$TMP\""
ABOUT=$RESULT
}
#------------------------------------------------ CDLOOKUP
function Lookup_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"
let COUNTER=$COUNTER+1
done
fi
# Lookup information from CDDB
$CDDA2WAV -D $CDROM -J -v titles -L 1 -N -H 2>&1 | tr -d "'" | $AWK '/Album/ {print} /Track/ {print}' > /tmp/CD.txt
# Determine amount of tracks (includes album title)
TRACKS=`cat /tmp/CD.txt | wc -l`
# If no tracks then reread CD
if [[ $TRACKS -lt 2 ]]
then
# Restore default title
if [[ $TRACKS -eq 1 ]]
then
L_TITLE=`cat /tmp/CD.txt | $AWK '/Album/ {print substr($0, index($0, ":") + 1)}'`
gtk "gtk_window_set_title $WINDOW \"$L_TITLE\""
else
gtk "gtk_window_set_title $WINDOW \"CD Player\""
fi
# Find amount of tracks on CD
$CDDA2WAV -D $CDROM -J -v toc -L 1 -N -H 2>&1 | tr -d "'" | $AWK 'BEGIN {ORS=""} /[0-9]:[0-9]/ {print}' > /tmp/CD.txt
TRACKS=`cat /tmp/CD.txt | $AWK 'BEGIN {RS=","} {print}' | wc -l`
# Add track numbering to combobox
COUNTER=0
until [[ $COUNTER -eq $TRACKS ]]
do
let TMP=$COUNTER+1
L_TRACK="$TMP - Unknown track"
gtk "gtk_combo_box_append_text $G_COMBO \"$L_TRACK\""
let COUNTER=$COUNTER+1
done
else
# Add CD title to window title
L_TITLE=`cat /tmp/CD.txt | $AWK '/Album/ {print substr($0, index($0, ":") + 1)}'`
gtk "gtk_window_set_title $WINDOW \"$L_TITLE\""
# Add tracks to combobox
COUNTER=1
until [[ $COUNTER -eq $TRACKS ]]
do
L_TRACK=`grep "Track $COUNTER" /tmp/CD.txt`
if [[ -z $L_TRACK ]]
then
L_TRACK=`grep "Track $COUNTER" /tmp/CD.txt`
fi
TMP=`echo $L_TRACK | $AWK '{gsub(/"/, ""); print}'`
gtk "g_locale_to_utf8 \"$TMP\" -1 NULL NULL NULL"
L_TRACK=$RESULT
gtk "gtk_combo_box_append_text $G_COMBO \"$L_TRACK\""
let COUNTER=$COUNTER+1
done
# Put amount of tracks to real value
((TRACKS-=1))
fi
# Put first item as active one
gtk "gtk_combo_box_set_active $G_COMBO 0"
}
#------------------------------------------------ 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
$SLEEP 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 -w $V_VOL;;
esac
}
#------------------------------------------------ MAIN
# Set global variables
CDROM=/dev/cdrom
# 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 UPDATE"
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
# Avoid 99% CPU load
$SLEEP 0.05
done
# Before exiting, stop playing CD
Stop_CD
# Remove temporary file
rm /tmp/CD.txt
# Exit GTK
gtk "gtk_exit 0"