diff --git a/src/OSC.jl b/src/OSC.jl index 105493d..366661c 100644 --- a/src/OSC.jl +++ b/src/OSC.jl @@ -5,6 +5,10 @@ macro incfp(x) quote begin gensym_ end end end +type OscMsg + data::Array{Uint8} +end + function stringify(data::Array{Uint8}) zeroInd = find(data.== 0) if(length(zeroInd) == 0) @@ -16,41 +20,41 @@ function stringify(data::Array{Uint8}) end end -function rtosc_argument_string(msg::Array{Uint8})#::ASCIIString +function names(msg::OscMsg)#::ASCIIString pos = 1 - while(msg[pos += 1] != 0) end #skip pattern - while(msg[pos += 1] == 0) end #skip null - return stringify(msg[pos+1:end]); #skip comma + while(msg.data[pos += 1] != 0) end #skip pattern + while(msg.data[pos += 1] == 0) end #skip null + return stringify(msg.data[pos+1:end]); #skip comma end strip_args(args::ASCIIString) = replace(replace(args,"]",""),"[","") -function rtosc_narguments(msg::Array{Uint8}) - length(strip_args(rtosc_argument_string(msg))) +function narguments(msg::OscMsg) + length(strip_args(names(msg))) end has_reserved(typeChar::Char) = typeChar in "isbfhtdSrmc" nreserved(args::ASCIIString) = sum(map(has_reserved, collect(args))) -function rtosc_type(msg::Array{Uint8}, nargument::Int)#::Char - @assert(nargument < rtosc_narguments(msg)); - return strip_args(rtosc_argument_string(msg))[nargument+1] +function argType(msg::OscMsg, nargument::Int)#::Char + @assert(nargument < narguments(msg)); + return strip_args(names(msg))[nargument+1] end align(pos) = pos+(4-(pos-1)%4) -function arg_off(msg::Array{Uint8}, idx::Int)#::Int - if(!has_reserved(rtosc_type(msg,idx))) +function arg_off(msg::OscMsg, idx::Int)#::Int + if(!has_reserved(argType(msg,idx))) return 0; end #Iterate to the right position - args::ASCIIString = rtosc_argument_string(msg); + args::ASCIIString = names(msg); argc::Int = 1 pos::Int = 1 #Get past the Argument String - while(msg[pos] != ',') pos += 1 end - while(msg[pos] != 0) pos += 1 end + while(msg.data[pos] != ',') pos += 1 end + while(msg.data[pos] != 0) pos += 1 end #Alignment pos = align(pos) @@ -67,13 +71,13 @@ function arg_off(msg::Array{Uint8}, idx::Int)#::Int elseif(arg in "mrfci") pos += 4; elseif(arg in "Ss") - while(msg[pos += 1] != 0) end + while(msg.data[pos += 1] != 0) end pos = align(pos) elseif(arg == 'b') - bundle_length |= (msg[@incfp(pos)] << 24); - bundle_length |= (msg[@incfp(pos)] << 16); - bundle_length |= (msg[@incfp(pos)] << 8); - bundle_length |= (msg[@incfp(pos)]); + bundle_length |= (msg.data[@incfp(pos)] << 24); + bundle_length |= (msg.data[@incfp(pos)] << 16); + bundle_length |= (msg.data[@incfp(pos)] << 8); + bundle_length |= (msg.data[@incfp(pos)]); bundle_length += 4-bundle_length%4; pos += bundle_length; elseif(arg in "[]")#completely ignore array chars @@ -192,8 +196,17 @@ function rtosc_amessage(buffer::Array{Uint8}, return pos-1; end -function rtosc_argument(msg::Array{Uint8}, idx::Int) - typeChar::Char = rtosc_type(msg, idx); +function message(address::ASCIIString, + arguments::ASCIIString, + args...) + len::Int = vsosc_null(address, arguments, args...); + data::Vector{Uint8} = Array(Uint8, len); + rtosc_amessage(data,len,address,arguments,args...); + return OscMsg(data) +end + +function rtosc_argument(msg::OscMsg, idx::Int) + typeChar::Char = argType(msg, idx); #trivial case if(!has_reserved(typeChar)) if(typeChar == 'T') @@ -206,14 +219,14 @@ function rtosc_argument(msg::Array{Uint8}, idx::Int) if(typeChar in "htd") t::Uint64 = 0 - t |= (uint64(msg[@incfp(arg_pos)]) << 56); - t |= (uint64(msg[@incfp(arg_pos)]) << 48); - t |= (uint64(msg[@incfp(arg_pos)]) << 40); - t |= (uint64(msg[@incfp(arg_pos)]) << 32); - t |= (uint64(msg[@incfp(arg_pos)]) << 24); - t |= (uint64(msg[@incfp(arg_pos)]) << 16); - t |= (uint64(msg[@incfp(arg_pos)]) << 8); - t |= (uint64(msg[@incfp(arg_pos)])); + t |= (uint64(msg.data[@incfp(arg_pos)]) << 56); + t |= (uint64(msg.data[@incfp(arg_pos)]) << 48); + t |= (uint64(msg.data[@incfp(arg_pos)]) << 40); + t |= (uint64(msg.data[@incfp(arg_pos)]) << 32); + t |= (uint64(msg.data[@incfp(arg_pos)]) << 24); + t |= (uint64(msg.data[@incfp(arg_pos)]) << 16); + t |= (uint64(msg.data[@incfp(arg_pos)]) << 8); + t |= (uint64(msg.data[@incfp(arg_pos)])); if(typeChar == 'h') return int64(t) elseif(typeChar == 'd') @@ -222,13 +235,13 @@ function rtosc_argument(msg::Array{Uint8}, idx::Int) return t; end elseif(typeChar in "f") - return reinterpret(Float32,msg[arg_pos+(3:-1:0)])[1] + return reinterpret(Float32,msg.data[arg_pos+(3:-1:0)])[1] elseif(typeChar in "rci") i::Int32 = 0 - i |= (uint32(msg[@incfp(arg_pos)]) << 24); - i |= (uint32(msg[@incfp(arg_pos)]) << 16); - i |= (uint32(msg[@incfp(arg_pos)]) << 8); - i |= (uint32(msg[@incfp(arg_pos)])); + i |= (uint32(msg.data[@incfp(arg_pos)]) << 24); + i |= (uint32(msg.data[@incfp(arg_pos)]) << 16); + i |= (uint32(msg.data[@incfp(arg_pos)]) << 8); + i |= (uint32(msg.data[@incfp(arg_pos)])); if(typeChar == 'r') return uint32(i) elseif(typeChar == 'c') @@ -238,23 +251,52 @@ function rtosc_argument(msg::Array{Uint8}, idx::Int) end elseif(typeChar in "m") m = Array(Uint8, 4) - m[1] = msg[@incfp(arg_pos)] - m[2] = msg[@incfp(arg_pos)] - m[3] = msg[@incfp(arg_pos)] - m[4] = msg[@incfp(arg_pos)] + m[1] = msg.data[@incfp(arg_pos)] + m[2] = msg.data[@incfp(arg_pos)] + m[3] = msg.data[@incfp(arg_pos)] + m[4] = msg.data[@incfp(arg_pos)] return m elseif(typeChar in "b") len::Int32 = 0 - len |= (msg[@incfp(arg_pos)] << 24); - len |= (msg[@incfp(arg_pos)] << 16); - len |= (msg[@incfp(arg_pos)] << 8); - len |= (msg[@incfp(arg_pos)]); - return msg[arg_pos+(0:len-1)]; + len |= (msg.data[@incfp(arg_pos)] << 24); + len |= (msg.data[@incfp(arg_pos)] << 16); + len |= (msg.data[@incfp(arg_pos)] << 8); + len |= (msg.data[@incfp(arg_pos)]); + return msg.data[arg_pos+(0:len-1)]; elseif(typeChar in "Ss") - return stringify(msg[arg_pos:end]); + return stringify(msg.data[arg_pos:end]); end end return nothing; end + +getindex(msg::OscMsg, idx::Int) = rtosc_argument(msg, idx) + +function show(msg::OscMsg) + println("OSC Message to ", stringify(msg.data)) + println(" Arguments:"); + for i=1:narguments(msg) + showField(msg,i) + end +end + +function showField(msg::OscMsg, arg_id) + map = ['i' Int32; 'f' Float32; 's' String; 'b' :Blob; 'h' Int32; 't' Uint64; + 'd' Float64; 'S' Symbol; 'c' Char; 'r' :RBG; 'm' :Midi; 'T' true; + 'F' false; 'N' Nothing] + dict = Dict{Char, Any}(map[:,1][:],map[:,2][:]) + dict['I'] = Inf + typeChar::Char = argType(msg, arg_id-1) + value = msg[arg_id-1] + if(issubtype(typeof(value), Array)) + value = value' + end + @printf(" #%2d %c:", arg_id, typeChar); + print(dict[typeChar]," - ", value) + if(!issubtype(typeof(value), Array)) + println() + end + +end end diff --git a/test/runtests.jl b/test/runtests.jl index 13e2d80..128ea74 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -36,29 +36,29 @@ function test_it_fat() #nil #inf - buffer = Array(Uint8, 1024); - len = OSC.rtosc_amessage(buffer, 1024, "/dest", + msg = OSC.message("/dest", "[ifsbhtdScrmTFNI]", i,f,s,b,h,t,d,S,c,r,m); + OSC.show(msg) #println(string(map(x->(hex(x,2)), buffer[1:len])...)) #println(string(map(x->(isprint(char(x&0x7f)) ? string(char(x&0x7f)," ") : ". "), buffer[1:len])...)) #println("argument string is=", rtosc_argument_string(buffer)) - @test OSC.rtosc_argument(buffer, 0) == i - @test OSC.rtosc_argument(buffer, 1) == f - @test OSC.rtosc_argument(buffer, 2) == s - @test OSC.stringify(OSC.rtosc_argument(buffer, 3)) == b - @test OSC.rtosc_argument(buffer, 4) == h - @test OSC.rtosc_argument(buffer, 5) == t - @test OSC.rtosc_argument(buffer, 6) == d - @test OSC.rtosc_argument(buffer, 7) == S - @test OSC.rtosc_argument(buffer, 8) == c - @test OSC.rtosc_argument(buffer, 9) == r - @test OSC.rtosc_argument(buffer, 10) == m - @test OSC.rtosc_type(buffer,11) == 'T' - @test OSC.rtosc_type(buffer,12) == 'F' - @test OSC.rtosc_type(buffer,13) == 'N' - @test OSC.rtosc_type(buffer,14) == 'I' + @test msg[0] == i + @test msg[1] == f + @test msg[2] == s + @test OSC.stringify(msg[3]) == b + @test msg[4] == h + @test msg[5] == t + @test msg[6] == d + @test msg[7] == S + @test msg[8] == c + @test msg[9] == r + @test msg[10] == m + @test OSC.argType(msg,11) == 'T' + @test OSC.argType(msg,12) == 'F' + @test OSC.argType(msg,13) == 'N' + @test OSC.argType(msg,14) == 'I' end function test_it_osc_spec() @@ -96,6 +96,7 @@ function test_it_osc_spec() println(string(map(x->(isprint(char(x&0x7f)) ? string(char(x&0x7f)," ") : ". "), message_one)...)) @test len == length(message_one) @test buffer[1:length(message_one)] == message_one + OSC.show(OSC.OscMsg(buffer)) len = OSC.rtosc_amessage(buffer, 256, "/foo", "iisff", int32(1000), int32(-1), "hello", float32(1.234), float32(5.678)) @@ -105,9 +106,11 @@ function test_it_osc_spec() println(string(map(x->(isprint(char(x&0x7f)) ? string(char(x&0x7f)," ") : ". "), message_two)...)) @test len == length(message_two) @test buffer[1:len] == message_two + OSC.show(OSC.OscMsg(buffer)) end if test_type in ["ALL", "TEST", "INSTALL"] test_it_osc_spec() test_it_fat() + println("Done...") end