#!/usr/bin/tclsh
#
# A simple sender test
#

package require udp

source oscPack.tcl
# Provides: proc packOSCpath {path types argList}
# Provides: proc makeElementFromPath  {path types argList}
# Provides: proc makeBundleFromElements {timestamp elementArray}

#
# In case we get a reply from a reflector....
#
source oscUnpack.tcl
# Provides: proc unpackOSCpath oscBinStr => multilevel list
# Provides: proc handleEvent oscBinStr

set fileTest 0

source osctime.tcl
set ::osctime::debug 1
#
# This takes too long....
#
::osctime::setup

source musys.conf.tcl

set myport $port(myapp)
set subnet $cast(OSCEAIgw)
set outgoing $port(OSCEAIgw)

if {$fileTest} {
	set udpSock [open {sampledata.bin} w]
	fconfigure $udpSock -buffering none -blocking 0 -translation binary
} else {
	# Create a listening socket and configure for sending too.
	set udpSock [udp_open $myport]
	fconfigure $udpSock -buffering none -blocking 0 -translation binary
	fconfigure $udpSock -broadcast 1 -remote [list $subnet $outgoing]
	fileevent  $udpSock readable [list oscMsgEvent $udpSock]
}

##########################################################################
proc testOSC {path types argList} {

	set debug $oscPack::debug

	if {$debug == 1} {
		puts stdout [format "Testing transmission with path=%s types={%s} values=\[%s\]" $path $types $argList]
	}

	set oscMsg [oscPack::packOSCpath $path $types $argList]

	if {[string length $oscMsg] > 0} {
		transmitOSC $oscMsg
	} else {
		puts stdout "FAILED oscPack::packOSCpath $path $types $argList"
	}
}
proc transmitOSC {oscMsg} {
	global udpSock outgoing
	puts -nonewline $udpSock $oscMsg
}
proc oscMsgEvent {chan} {
	set debug $oscPack::debug
	set debug 1

	set oscMsg [read $chan]
	set peer [fconfigure $chan -peer]
	#
	# Hmm.. we do not always seem to get the data in one read.
	# 4K boundaries in read buffer ?
	#
	set gotMore 1
	while {$gotMore > 0} {
		after 1
		set moreData [read $chan]
		set gotMore [string length $moreData]
		if {$gotMore > 0} {
			puts "oscMsgEvent Drips and drabs: add $gotMore bytes to [string length $oscMsg] bytes"
			append oscMsg $moreData
		}
	}
	if {$debug == 1} {
		puts "$peer sent [string length $oscMsg] bytes"
	}
	if {[string length $oscMsg] > 0} {
		# We are running in decode mode
		set unpacked [oscUnpack::unpackOSCpath $oscMsg]
		puts stdout "$unpacked"
	}
	return
}
##########################################################################

set path {/alpha/beta/gamma}

set ::oscPack::haveGivenHexBlob 1
set ::oscPack::havePackedMidi 0

set iTimeStamp [::osctime::nowToOscTime]
set portId 11
set statusByte 0xa0
set data1 65
set data2 0

if {1 == 1} {

	set types {tidsstiTsFNIssficbcsmssts}
	set argList [list $iTimeStamp 32768 6.66666666666 omega gamma $iTimeStamp 0 alpha beta alpha 12345.67890 1 a {001133557799bbddff00} a alpha $portId $statusByte $data1 $data2 beta alpha $iTimeStamp beta]

	testOSC $path $types $argList
}

if {1 == 1} {
	# Simple bundle-test

	set types {tidsstiTsFNIssficbcsmssts}
	set argList [list $iTimeStamp 32768 6.66666666666 omega gamma $iTimeStamp 0 alpha beta alpha 12345.67890 1 a {001133557799bbddff00} a alpha $portId $statusByte $data1 $data2 beta alpha $iTimeStamp beta]

	set oscBundlePiece [::oscPack::makeElementFromPath $path $types $argList]

	set iTimeStamp [::osctime::futureToOscTime 5 15 1000]	; # now plus 5 and 15/1000th seconds into the future
	set oscBundleElement(0) $oscBundlePiece
	set oscBundleElement(1) $oscBundlePiece
	set oscBundleElement(2) $oscBundlePiece
	set oscBundleElement(3) $oscBundlePiece

	set bundle [::oscPack::makeBundleFromElements $iTimeStamp oscBundleElement]

	transmitOSC $bundle
}

if {1 == 0} {
	# test the 4 Symbolic options
	# Note, these do NOT affect what is sent/received, it ONLY
	# affects what you give and receive from that pack/unpack routines

	set types {iTsFNIs}
	set ::oscPack::haveGivenSymbols 0
		set argList [list 32768 alpha beta]
		testOSC $path $types $argList

	set ::oscPack::haveGivenSymbols 1
		set argList [list 32768 1 alpha 0 {} NaN beta]
		testOSC $path $types $argList
}


if {1 == 0} {
	# Blob test
	set ::oscPack::haveGivenHexBlob 1
	set types {sbs}
	set argList [list a {001133557799bbddff00} a]
	testOSC $path $types $argList
}

if {1 == 0} {
	# Midi, both packed and unpacked
	set types {sms}

	set oscPack::havePackedMidi 1
	if {$oscPack::havePackedMidi} {
		binary scan [binary format cccc [expr 0xff&$portId] [expr 0xff&$statusByte] [expr 0xff&$data1] [expr 0xff&$data2]] I pMidi
		puts stdout [format "Packed midi %x from %d %d %d %d" $pMidi $portId $statusByte $data1 $data2]
		set argList [list alpha $pMidi beta]
	} else {
		set argList [list alpha $portId $statusByte $data1 $data2 beta]
	}
	testOSC $path $types $argList

	set oscPack::havePackedMidi 0
	if {$oscPack::havePackedMidi} {
		binary scan [binary format cccc [expr 0xff&$portId] [expr 0xff&$statusByte] [expr 0xff&$data1] [expr 0xff&$data2]] I pMidi
		puts stdout [format "Packed midi %x from %d %d %d %d" $pMidi $portId $statusByte $data1 $data2]
		set argList [list alpha $pMidi beta]
	} else {
		set argList [list alpha $portId $statusByte $data1 $data2 beta]
	}
	testOSC $path $types $argList
}

if {1 == 0} {
	# Timestamps
	set iTimeStamp [::osctime::nowToOscTime]
	set types {sts}
	set argList [list alpha $iTimeStamp beta]
	testOSC $path $types $argList

	set iTimeStamp [::osctime::futureToOscTime 5 15 1000]	; # now plus 5 and 15/1000th seconds into the future
	set argList [list alpha $iTimeStamp beta]
	testOSC $path $types $argList

	set iTimeStamp [::osctime::instant]
	set argList [list alpha $iTimeStamp beta]
	testOSC $path $types $argList
}

if {$fileTest} {
	close $udpSock
} else {
	set forever 0
	vwait ::forever
}
