routing.lua 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. local osc = require("osc")
  2. local routing = {}
  3. -- a map of incoming to outgoing addresses
  4. -- each entry will contain a collection of entries
  5. local routingTable = {}
  6. -- local exampleRtEntry = {
  7. -- incoming = "/incoming/addr",
  8. -- outgoing = "/outgoing/addr",
  9. -- swizzle = {1,22,333,22,1},
  10. -- originalString = "/incoming/addr /outgoing/addr 1 22 333 22 1"
  11. -- origin = "path/to/file.txt" or "cmd"
  12. -- }
  13. -- adds a single routing string to the table
  14. function routing.addFromString(rawRouting, originName)
  15. local newEntry = {
  16. origin = originName,
  17. originalString = rawRouting,
  18. }
  19. -- grab adresses
  20. local addressMatcher = rawRouting:gmatch("[^%s]+")
  21. newEntry.incoming = addressMatcher()
  22. newEntry.outgoing = addressMatcher()
  23. -- grab swizzles and literals
  24. local _, ogEnd = rawRouting:find(newEntry.outgoing)
  25. local swizzleString = rawRouting:sub(ogEnd+1)
  26. local swizzleMatcher = swizzleString:gmatch("[^ ]+", ogEnd)
  27. newEntry.swizzle = {}
  28. for n in swizzleMatcher do
  29. if(tonumber(n)) then
  30. table.insert(newEntry.swizzle, tonumber(n))
  31. elseif n:match("\"(.*)\"") then
  32. table.insert(newEntry.swizzle, n:match("\"(.*)\""))
  33. elseif n:match(".*\.lua") then
  34. print("oscoroutines coming soon")
  35. -- require the
  36. else
  37. table.insert(newEntry.swizzle, n)
  38. end
  39. end
  40. -- make an entry in the table for this incoming if it is needed
  41. if not routingTable[newEntry.incoming] then
  42. routingTable[newEntry.incoming] = {}
  43. end
  44. -- insert our entry
  45. table.insert(routingTable[newEntry.incoming], newEntry)
  46. end
  47. -- adds a osc message to the routing table
  48. function routing.addFromMessage(msg)
  49. end
  50. -- adds a table of routing strings
  51. function routing.addFromTable(table)
  52. for _, v in pairs(table) do
  53. -- i added the : because it basically cant appera in a filename on any major OS
  54. routing.addFromString(v,":table")
  55. end
  56. end
  57. -- adds a file of routing strings, one per line
  58. function routing.addFromFile(filename)
  59. -- remove anything from this origin
  60. for name, incoming in pairs(routingTable) do
  61. local toRemove = {}
  62. for i=1,#incoming,1 do
  63. if incoming[i].origin == filename then
  64. table.insert(toRemove,i)
  65. end
  66. end
  67. for i=1,#toRemove,1 do
  68. incoming[i] = incoming[#incoming]
  69. table.remove(incoming)
  70. end
  71. end
  72. -- add all the stuff back in
  73. for line in io.lines(filename) do
  74. if line:match("[^%s]+") then
  75. routing.addFromString(line,filename)
  76. end
  77. end
  78. end
  79. local function routerHelper(routings, incomingMessage)
  80. local outgoingMessages = {}
  81. for _, route in pairs(routings) do
  82. local newaddr = osc.toOSCString(route.outgoing)
  83. -- create a new message
  84. local newMsg = osc.create(newaddr)
  85. -- loop over swizzles and add the appropriate arguments
  86. for _, s in pairs(route.swizzle) do
  87. if type(s) == "number" and math.floor(s) == s then
  88. osc.appendArgument(newMsg, incomingMessage[s], incomingMessage.argString:sub(s+1,s+1))
  89. elseif s:match("#%d+") then
  90. local nStr = tonumber(s:match("%d+"))
  91. osc.appendArgument(newMsg,nStr)
  92. elseif s:match('[^%z]+') then
  93. local stringLit = s:match('[^%z]+')
  94. osc.appendArgument(newMsg, stringLit)
  95. else
  96. error("invalid swizzle" .. "(" .. s .. ")")
  97. end
  98. end
  99. table.insert(outgoingMessages, newMsg)
  100. end
  101. return outgoingMessages
  102. end
  103. function routing.createRoutedMessages(incomingMessage)
  104. local searchStr = incomingMessage.addr:match("[^%z]+")
  105. local routings = routingTable[searchStr]
  106. if incomingMessage.addr:match("/rerouterator/started") then
  107. if routings then
  108. return routerHelper(routings, incomingMessage)
  109. end
  110. elseif incomingMessage.addr:match("/rerouterator/.*") then
  111. print("control messages not yet supported")
  112. elseif not routings then
  113. -- we have no appropriate rules just forward the message unaltered
  114. return {incomingMessage}
  115. else
  116. return routerHelper(routings, incomingMessage)
  117. end
  118. return {}
  119. end
  120. return routing