1 -- Swamp Bike Opera embedded system for Kaffe Matthews
2 -- Copyright (C) 2012 Wolfgang Hauptfleisch, Dave Griffiths
4 -- This program is free software: you can redistribute it and/or modify
5 -- it under the terms of the GNU General Public License as published by
6 -- the Free Software Foundation, either version 3 of the License, or
7 -- (at your option) any later version.
9 -- This program is distributed in the hope that it will be useful,
10 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
11 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 -- GNU General Public License for more details.
14 -- You should have received a copy of the GNU General Public License
15 -- along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module("engine", package.seeall)
28 ----------------------------------------------------------------
34 -- name="directional",
39 ----------------------------------------------------------------
41 function gpslog(lat, lon)
42 local file = io.open(CONFIG.install_path.."log/gps.log", "a")
43 local logmessage = os.date().." "..lat.." "..lon.."\n"
44 file:write(logmessage)
48 function log(logmessage)
49 print(os.date().." "..logmessage)
55 --os.execute("espeak \""..txt.."\"")
59 ----------------------------------------------------------------
61 function read_events(events)
64 for k,layer in pairs(events) do
65 for k,event in pairs(layer) do
66 txt=txt.." "..event.type.." ".." "..event.zone_colour.." "..
67 event.zone_name.." in "..event.layer_name.."."
73 ----------------------------------------------------------------
75 function dispatch_override(event,pos_state,override)
76 if override.name=="directional" then
77 play_directional(event,pos_state,override)
81 ----------------------------------------------------------------
83 function play_directional(event,pos_state,override)
84 --utils.table_print(override)
86 --print(direction.pan_from(pos_state.dir,override.dir))
88 if event.type=="entered-zone" then
89 -- print(direction.resolve(poly.angle(pos_state.dir)))
90 -- utils.table_print(pos_state.dir)
91 -- print(override.dir)
92 audioc.loop(event.zone_name,
93 direction.pan_from(pos_state.dir,override.dir))
95 if event.type=="left-zone" then
96 audioc.stop(event.zone_name)
108 -- return true if facing in same direction (with 90 deg tolerance)
109 -- this is stupid and dumb version
110 function direction_compare(one,two)
112 return utils.find_value(two,{"n","nw","n","ne","e"});
114 if (one == "ne") then
115 return utils.find_value(two,{"nw","n","ne","e","se"});
118 return utils.find_value(two,{"n","ne","e","se","s"});
120 if (one == "se") then
121 return utils.find_value(two,{"ne","e","se","s","sw"});
124 return utils.find_value(two,{"e","se","s","sw","w"});
126 if (one == "sw") then
127 return utils.find_value(two,{"se","s","sw","w","nw"});
130 return utils.find_value(two,{"s","sw","w","nw","n"});
132 if (one == "nw") then
133 return utils.find_value(two,{"sw","w","nw","n","ne"});
139 function cats_to_direction(parent,cats)
140 if (utils.find_value(parent..":North",cats)) then
141 if (utils.find_value(parent..":East",cats)) then
144 if (utils.find_value(parent..":West",cats)) then
149 if (utils.find_value(parent..":South",cats)) then
150 if (utils.find_value(parent..":East",cats)) then
153 if (utils.find_value(parent..":West",cats)) then
158 if (utils.find_value(parent..":West",cats)) then
161 if (utils.find_value(parent..":East",cats)) then
167 ----------------------------------------------------------------
168 -- not sure this is the best place for this!
169 local panned_samples={}
170 local one_shot_samples={}
172 function play_events(events,pos_state)
174 -- first if the direction has been updated, go through
175 -- all the panned samples
176 if pos_state.new_direction then
177 print("updating direction")
178 for name,dir in pairs(panned_samples) do
179 local pan=direction.pan_from(pos_state.dir,dir)
180 print("shifting "..name.." to "..pan)
181 audioc.shift(name,pan)
185 -- now look through all the maps for new events
186 for k,layer in pairs(events) do
187 for k,event in pairs(layer) do
188 engine.log(event.type.." "..event.zone_name.." in "..event.layer_name)
190 local switch_dir = cats_to_direction("Direction Parameter",event.zone_categories)
191 local heading = direction.resolve(poly.angle(pos_state.dir))
193 if (switch_dir~="centre") then
194 -- if this zone is using a direction to switch, check here
195 print("DIRECTIONAL--->"..switch_dir.." vs current "..heading)
196 if (direction_compare(switch_dir,heading)) then
203 if switch_dir=="centre" or direction_compare(switch_dir,heading) then
205 local name=event.zone_name
207 if (utils.find_value("Sample Parameters:Loop",event.zone_categories)) then
210 local dir=cats_to_direction("Pan Parameter",event.zone_categories)
212 -- is it a one shot sample?
213 if (utils.find_value("Sample Parameters:One shot",event.zone_categories)) then
214 one_shot_samples[name]="yes"
217 -- look for an override
218 local override=overrides[event.zone_name]
220 dispatch_override(event,pos_state,override)
223 if event.type=="entered-zone" then
224 if dir=="centre" then ----- normal -------
230 else ------- directional ---------------
231 -- add to panned samples so we can update it later
232 panned_samples[name]=dir
233 print("added panned "..name.." "..dir)
234 local pan=direction.pan_from(pos_state.dir,dir)
236 audioc.play(name,pan)
238 audioc.loop(name,pan)
244 if event.type=="left-zone" then
245 if panned_samples[name] then
246 panned_samples[name]=nil
249 if one_shot_samples[name]~="yes" then
258 ----------------------------------------------------------------------
260 function update_pos_state(pos,state)
261 -- calculate distance since last time
262 local time_diff = os.time() - state.time
264 state.new_direction=false
266 if time_diff > CONFIG.direction_track_time then
267 state.time = os.time()
269 local distance=poly.distance_km(pos.lat, pos.lng,
270 state.pos.lat, state.pos.lng);
271 state.speed=distance/CONFIG.direction_track_time;
272 state.dir={lat=pos.lat-state.pos.lat,
273 lng=pos.lng-state.pos.lng}
276 state.new_direction=true
278 log("speed is "..state.speed.."km/h"..
279 " direction is "..direction.resolve(poly.angle(state.dir)))
284 ----------------------------------------------------------------
286 function load_events(events,pos_state)
287 for k,layer in pairs(events) do
288 for k,event in pairs(layer) do
289 engine.log("load event: "..event.type.." "..event.zone_name.." in "..event.layer_name)
291 -- zone name consists of:
292 -- <name>_<loop>_<direction>_<ghost>
293 local tokens=std.split(event.zone_name,"_")
299 if event.type=="entered-zone" then
302 if event.type=="left-zone" then