#################################
# The PlayPanel Module
#
# Part of the SharpeSound Editor
# by Paul D. Sharpe
# A 3rd Year Project at the University of Leeds;
# Department of Electronic and Electrical Engineering.
# Date: 15/2/95
#
# Revision:3a 
# Date: 2/3/95

##########################
# playPanel - Is the procedure that setups and displays the panel containing 
# the play, record and stop buttons. 
# There are 3 options.
# 1. init : this sets up   but doesn't display them.
# 2. show : this packs.
# 3. noshow this unpacks.
proc PlayPanel { option } {

   global ConfigSet FILE PLAY


   # Other Settings
   set PLAY(ButtList) [list Play Record Stop]
   set Playicon "@$FILE(SRC)\/play.ico"
   set Recordicon  "@$FILE(SRC)\/rec.ico"
   set Stopicon "@$FILE(SRC)\/stop.ico"
   set ButtWidth 30


   if {$option == "init" } {
      if {![winfo exists .playpanel]} {
	# Create the play panel widgets.

	frame .playpanel -background $ConfigSet(cBG1)
	frame .playpanel.title 
	label .playpanel.title.label -text Controls
	label .playpanel.title.timel -text "Play Time:" -anchor e
	label .playpanel.title.time -textvariable PLAY(Time)\
				     -width 3 -anchor w
	pack .playpanel.title.label -side left -fill x -expand 1\
		-anchor w -ipady 1m
	pack .playpanel.title.timel .playpanel.title.time -side left\
			-ipady 1m

	# Create the Buttons
	foreach Button $PLAY(ButtList) {
		# Each Button is to consist of a button
		# and a label
		
		# Make Button lower case for widget creation
		set button [string tolower $Button]

		# Create the frame to contain these.
		frame .playpanel.$button

		# Set the icon and command name for the buttons.
		eval set icon $[format "%sicon" $Button]
		set command $Button

		# Create the button.
		button .playpanel.$button.button \
			-bitmap $icon \
			-command $command
			

		# Create the label.
		label .playpanel.$button.label \
				-text $Button
		# Pack.
		pack .playpanel.$button.button .playpanel.$button.label\
			-side top -fill x   	
		pack .playpanel.$button  \
			-side left -fill x -expand 1 -padx 2
		# Bind record button to call up box to set recording
		# settings
		if {$button=="record"} {
			bind .playpanel.$button.button <Button-3> { Settings }
		}
	}

	# Packing.
	pack .playpanel.title \
		-side top \
		-before .playpanel.[string tolower [lindex $PLAY(ButtList) 0]]\
		-fill x -expand 1

	# Set the Button states and start the checking routine
	PP_Playing
	PP_ButtonAble
      }
      # Configure the PlayPanel widgets.
      .playpanel config -background $ConfigSet(cBG1)\
		-borderwidth $ConfigSet(BDW)\
			-relief $ConfigSet(REL)
	
      .playpanel.title.label config \
			-background $ConfigSet(cBG1)
      .playpanel.title.label config \
			-background $ConfigSet(cBG1) \
			-foreground $ConfigSet(cFG1) \
			-anchor w \
			-font $ConfigSet(FNT_S)

      .playpanel.title.timel config \
			-background $ConfigSet(cBG1) \
			-foreground $ConfigSet(cFG1) \
			-anchor w \
			-font $ConfigSet(FNT_S)
      .playpanel.title.time  config \
			-background $ConfigSet(cBG1) \
			-foreground $ConfigSet(cFG1) \
			-anchor w \
			-font $ConfigSet(FNT_S)

      # Configure the Buttons
      foreach Button $PLAY(ButtList) {

	# Make Button lower case for widget creation
	set button [string tolower $Button]

	# Configure the frame to contain these.
	.playpanel.$button config -background $ConfigSet(cBG1)

	# Configure the button.
	 .playpanel.$button.button config\
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-width $ButtWidth

	# Configure the label.
	 .playpanel.$button.label config \
				-background $ConfigSet(cBG1) \
				-foreground $ConfigSet(cFG1) \
				-anchor w \
				-font $ConfigSet(FNT_S)
      }

   # The show option.
   } \
   elseif {$option == "show"} { 
	global PACK
	if {$PACK(PlayPanel) != ""} {
		pack .playpanel -fill x -after $PACK(PlayPanel)
	}  else {
		pack .playpanel -fill x
	}

   # the No show option.			 
   } \
   elseif {$option == "noshow" } { pack forget .playpanel } 
}

###################################################################
# Play
# This procedure is the callback to the play button in the play panel.
# It plays back the sample in the sound card.
proc Play {} {
   global  FILE FLAG FX PLAY DialogCfg LOAD

   # Only play if there is a loaded file and a sound card is detected.
   if {$FLAG(Loaded) && $FLAG(Card_Exist)} {		
     set test [catch {exec $FILE(Tool) diagnostics} err ]
     if {$test} {
	dialog .err Error \
		[format "Cannot record\nThe Sound Card is not available"]\
		 $DialogCfg {error} {0} {OK}
	
     } else {
	# Set the play-back source,based on whether the sample is marked or not.
	if {$FLAG(Marked)} {
		Copy $FILE(TMP3)
		set source $FILE(TMP3)
	} else {
		set source $FILE(TMP1)
	}

	# Apply Effects temporarily if in Preview Mode
	if {$FX(Preview)} {
		set source [AddFX]  
	}\
	else {
		if {$FLAG(Marked)} {
			Copy $FILE(TMP3)
			set source $FILE(TMP3)
		} else {
			set source $FILE(TMP1)
		}
	} 

	# Set state variables.
  	set PLAY(Time) 0
  	set FLAG(Playing) 1
  	PP_ButtonAble

	# Play the sample.
	set  FILE(PID)  [exec $FILE(Tool) play $source $LOAD(bit)\
		$LOAD(chnl) $LOAD(rate) &]
     }
   }
}



###################################################################
# Stop
# This procedure is the callback to the stop button in the play panel.
# It simply kills the processes whose IDs is stored in FILE(PID) and
# sets the state variables.
proc Stop {} {
   global FILE FLAG
   foreach pid $FILE(PID) {
	catch {exec kill $pid}

   }

   # Set the state variables.
   set FLAG(Playing) 0
   PP_ButtonAble
   update idletasks

   # Add a recorded to the sample if required.
   if {$FLAG(Recording)} {
  	Paste $FILE(TMP3)
	set FLAG(Recording) 0
   }
}

###################################################################
# Record
# This procedure is the callback to the record button in the play panel.
# It causes the sound card to receive data and stores this data.
proc Record {} {
   global FILE INFO SAMPLE FLAG DialogCfg LOAD

    # Record and check that card is available
    set test [catch {exec $FILE(Tool) diagnostics} err ]
   if {$test} {
	dialog .err Error \
		[format "Cannot record\nThe Sound Card is not available"]\
		 $DialogCfg {error} {0} {OK}
	
   } else {   

	# Set the recording parameters as set by user if it is a 
	# fresh recording (ie. not recording into a loaded file).
	if { !$FLAG(Loaded) } {
		set LOAD(bit) $SAMPLE(bit)
		set LOAD(chnl) $SAMPLE(chnl)
		set LOAD(rate) $SAMPLE(rate)
	}
	# Set Flags
	set FLAG(Playing) 1
	set FLAG(Recording) 1
	set FLAG(Loaded) 1

	# Enable Stop Button
	PP_ButtonAble

	# Record
	set FILE(PID) [exec $FILE(Tool) rec $FILE(TMP3)\
			 $LOAD(bit) $LOAD(chnl) $LOAD(rate) &]


   }
}

###################################################################
# PP_ButtonAble
# This procedure sets the states of the play panel buttons according
# to the state flags.
proc PP_ButtonAble {} {
   global FLAG
   if {$FLAG(Loaded)} {
     if {$FLAG(Playing)} {
   	.playpanel.stop.button configure -state normal
   	.playpanel.record.button configure -state disabled
   	.playpanel.play.button configure -state disabled
     } else {
   	.playpanel.stop.button configure -state disabled
   	.playpanel.record.button configure -state normal
   	.playpanel.play.button configure -state normal
     } 
  }\
  else {
  	.playpanel.stop.button configure -state disabled
   	.playpanel.record.button configure -state normal
   	.playpanel.play.button configure -state disabled
  }
}


###################################################################
# PP_Playing
# This procedure is a procedure which produces the estimated play
# time. It runs continuously in the background after being invoked once.
# It only actually does anything if Sound Studio is in the state of
# playing or recording (FLAG(Playing)).
# It updates the estimated time (PLAY(Time)), by detecting a difference
# in the current system clock to that stored from the last time PP_Playing
# called itself (PLAY(TimeMark)).
proc PP_Playing {} {

   global FILE FLAG PLAY

   if {$FLAG(Playing)} {
      # Compare the time mark.
      if {$PLAY(TimeMark)!=0} {
	set temp $PLAY(TimeMark)
	set PLAY(TimeMark) [exec date +%s]
	set PLAY(Time) [expr $PLAY(Time)+($PLAY(TimeMark) -$temp)]
	update idletasks

      # Set the time mark (the first time).
      } else {
	set PLAY(Time) 0
	set PLAY(TimeMark) [exec date +%s] }

	# Detect the end of the play/record process.
	if {[catch {exec ls /proc/$FILE(PID)}]} {
		Stop
	}

   # Sound Studio is not playing.
   } else {
	set PLAY(TimeMark) 0
   }

   # Call this procedure again after 100ms.
   after 100 PP_Playing
}
