source: other-projects/tipple-android/trunk/src/org/greenstone/android/tipple/TipLocationManager.java@ 23977

Last change on this file since 23977 was 23977, checked in by davidb, 13 years ago

Initial set of files for the Tipple project, to be run on an Android device

File size: 14.4 KB
Line 
1package org.greenstone.android.tipple;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.util.ArrayList;
6import java.util.HashMap;
7import java.util.List;
8
9import javax.xml.parsers.SAXParser;
10import javax.xml.parsers.SAXParserFactory;
11
12import org.greenstone.android.tipple.R;
13import org.mapsforge.android.maps.ArrayItemizedTextAudioOverlay;
14import org.mapsforge.android.maps.CirclesOverlay;
15import org.mapsforge.android.maps.GeoPoint;
16import org.mapsforge.android.maps.MapView;
17import org.mapsforge.android.maps.Overlay;
18import org.mapsforge.android.maps.OverlayItem;
19import org.mapsforge.android.maps.OverlayTextAudioItem;
20import org.mapsforge.android.maps.RouteOverlayResetable;
21import org.xml.sax.InputSource;
22import org.xml.sax.XMLReader;
23
24import android.app.Activity;
25import android.graphics.Color;
26import android.graphics.DashPathEffect;
27import android.graphics.Paint;
28import android.graphics.drawable.Drawable;
29import android.speech.tts.TextToSpeech;
30import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
31import android.util.Log;
32
33public class TipLocationManager
34{
35 Activity activity_;
36 AudioPlayerView audio_player_view_;
37 TextToSpeech tts_;
38
39 public static CirclesOverlay circlesOverlay=null;
40 public static ArrayItemizedTextAudioOverlay itemizedMarkerOverlay;
41 public static ArrayList<OverlayItem> itemizedMarkerOverlayArrayList;
42 public static ArrayList<GeoPoint> circlesOverlayGeoPoints;
43 public static ArrayList<Integer> circlesOverlayRadii;
44
45 public static RouteOverlayResetable routeOverlay=null;
46 public static ArrayItemizedTextAudioOverlay routeMarkerOverlay;
47 public static GeoPoint[] routeOverlayArray;
48
49 public static ArrayList<OverlayItem> routeMarkerOverlayArrayList;
50
51 public static String prevVisitedFilename;
52
53 TipLocationManager(Activity activity, AudioPlayerView audio_player_view,
54 TextToSpeech tts)
55 {
56 activity_ = activity;
57 audio_player_view_ = audio_player_view;
58 tts_ = tts;
59
60
61
62 }
63
64 protected void createLogRouteLocationsOverlay(MapView mapView,ArrayList<TipLocation> locations)
65 {
66 Paint fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
67 fillPaint.setStyle(Paint.Style.STROKE);
68 fillPaint.setColor(Color.BLUE);
69 fillPaint.setAlpha(160);
70 fillPaint.setStrokeWidth(7);
71 fillPaint.setStrokeCap(Paint.Cap.BUTT);
72 fillPaint.setStrokeJoin(Paint.Join.ROUND);
73 fillPaint.setPathEffect(new DashPathEffect(new float[] { 20, 20 }, 0));
74
75 Paint outlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
76 outlinePaint.setStyle(Paint.Style.STROKE);
77 outlinePaint.setColor(Color.BLUE);
78 outlinePaint.setAlpha(96);
79 outlinePaint.setStrokeWidth(7);
80 outlinePaint.setStrokeCap(Paint.Cap.BUTT);
81 outlinePaint.setStrokeJoin(Paint.Join.ROUND);
82
83 Drawable defaultMarker = activity_.getResources().getDrawable(R.drawable.routemarker);
84
85 if (routeOverlay==null) {
86 routeOverlay = new RouteOverlayResetable(fillPaint, outlinePaint);
87 routeMarkerOverlay = new ArrayItemizedTextAudioOverlay(defaultMarker,activity_,tts_);
88 routeMarkerOverlayArrayList = new ArrayList<OverlayItem>();
89
90 }
91 // This one needs to be done again, incase it is of a different size
92 routeOverlayArray = new GeoPoint[locations.size()];
93
94 for (int i=0; i<locations.size(); i++) {
95 TipLocation location = locations.get(i);
96 double latitude = location.getLatitude();
97 double longitude = location.getLongitude();
98 String title = location.getTitle();
99 String text = location.getText();
100 String tts_text = location.getTTSText();
101 GeoPoint geoPoint = new GeoPoint(latitude,longitude);
102
103 routeOverlayArray[i] = geoPoint;
104
105 if (title.startsWith("Manual")) {
106 // ItemizedOverlay => display marker with text for info pop-up window
107 OverlayTextAudioItem overlayItem = new OverlayTextAudioItem(geoPoint, title, text, tts_text);
108
109 //routeMarkerOverlay.addOverlay(overlayItem);
110 routeMarkerOverlayArrayList.add(overlayItem);
111 }
112 }
113
114 //routeOverlay.setRouteData(routeOverlayArray);
115
116 // Only add in if not already present
117 List<Overlay> overlays = mapView.getOverlays();
118 if (!overlays.contains(routeOverlay)) {
119 overlays.add(routeOverlay);
120 }
121 if (!overlays.contains(routeMarkerOverlay)) {
122 overlays.add(routeMarkerOverlay);
123 }
124 }
125
126 protected void addLogRouteLocations(MapView mapView)
127 {
128 for (int i=0; i<routeMarkerOverlayArrayList.size(); i++) {
129
130 OverlayItem overlay_item = routeMarkerOverlayArrayList.get(i);
131 routeMarkerOverlay.addOverlay(overlay_item);
132 }
133
134 routeOverlay.setRouteData(routeOverlayArray);
135
136 mapView.invalidate();
137
138 }
139
140 protected void removeLogRouteLocations(MapView mapView)
141 {
142 for (int i=0; i<routeMarkerOverlayArrayList.size(); i++) {
143
144 OverlayItem overlay_item = routeMarkerOverlayArrayList.get(i);
145 routeMarkerOverlay.removeOverlay(overlay_item);
146
147 }
148
149 routeOverlay.reset();
150
151 mapView.invalidate();
152 }
153
154 protected void createTourLocationsOverlay(MapView mapView, ArrayList<TipLocation> locations)
155 {
156 Paint circleFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
157 circleFillPaint.setStyle(Paint.Style.FILL);
158 circleFillPaint.setColor(Color.BLUE);
159 circleFillPaint.setAlpha(64);
160
161 Paint circleOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
162 circleOutlinePaint.setStyle(Paint.Style.STROKE);
163 circleOutlinePaint.setColor(Color.BLUE);
164 circleOutlinePaint.setAlpha(128);
165 circleOutlinePaint.setStrokeWidth(3);
166
167 Drawable defaultMarker = activity_.getResources().getDrawable(R.drawable.marker);
168
169 if (circlesOverlay==null) {
170 circlesOverlay = new CirclesOverlay(circleFillPaint, circleOutlinePaint);
171 circlesOverlayGeoPoints = new ArrayList<GeoPoint>();
172 circlesOverlayRadii = new ArrayList<Integer>();
173
174 itemizedMarkerOverlay = new ArrayItemizedTextAudioOverlay(defaultMarker,activity_,tts_);
175 itemizedMarkerOverlayArrayList = new ArrayList<OverlayItem>();
176 }
177
178 for (int i=0; i<locations.size(); i++) {
179 TipLocation location = locations.get(i);
180 double latitude = location.getLatitude();
181 double longitude = location.getLongitude();
182 int radius = (int)Math.round(1000.0 * location.getRadiusKM());
183 String title = location.getTitle();
184 String text = location.getText();
185 String tts_text = location.getTTSText();
186 GeoPoint geoPoint = new GeoPoint(latitude,longitude);
187
188 // CirclesOverlay => Highlight location with a circle showing catchment radius
189 //circlesOverlay.addCircleData(geoPoint, radius);
190 circlesOverlayGeoPoints.add(geoPoint);
191 circlesOverlayRadii.add(radius);
192
193 // ItemizedOverlay => display marker with text for info pop-up window
194 OverlayTextAudioItem overlayItem = new OverlayTextAudioItem(geoPoint, title, text, tts_text);
195
196 //itemizedMarkerOverlay.addOverlay(overlayItem);
197 itemizedMarkerOverlayArrayList.add(overlayItem);
198 }
199
200 // Only add in if not already present
201 List<Overlay> overlays = mapView.getOverlays();
202 if (!overlays.contains(itemizedMarkerOverlay)) {
203 overlays.add(itemizedMarkerOverlay);
204 }
205 if (!overlays.contains(circlesOverlay)) {
206 overlays.add(circlesOverlay);
207 }
208 }
209
210
211 protected void addTourLocations(MapView mapView)
212 {
213 for (int i=0; i<itemizedMarkerOverlayArrayList.size(); i++) {
214
215 OverlayItem overlay_item = itemizedMarkerOverlayArrayList.get(i);
216 itemizedMarkerOverlay.addOverlay(overlay_item);
217
218 GeoPoint geo_point = circlesOverlayGeoPoints.get(i);
219 int radius = circlesOverlayRadii.get(i);
220 circlesOverlay.addCircleData(geo_point, radius);
221 }
222
223 mapView.invalidate();
224 }
225
226 protected void removeTourLocations(MapView mapView)
227 {
228 for (int i=0; i<itemizedMarkerOverlayArrayList.size(); i++) {
229
230 OverlayItem overlay_item = itemizedMarkerOverlayArrayList.get(i);
231 itemizedMarkerOverlay.removeOverlay(overlay_item);
232 }
233
234 circlesOverlay.reset();
235
236 mapView.invalidate();
237
238 }
239
240 protected ArrayList<HashMap<String,String>> parseXMLToHashMapArrayList(String xml_filename,String lock_on_element)
241 {
242 ArrayList<HashMap<String,String>> hashmap_list = null;
243
244 try {
245
246 // set up XML parser
247 SAXParserFactory spf = SAXParserFactory.newInstance();
248 SAXParser sp = spf.newSAXParser();
249 XMLReader xr = sp.getXMLReader();
250
251 // Create handler that maps XML Tags within <Location> to a hashmap
252 XMLToHashmapHandler xmlTourHandler = new XMLToHashmapHandler(lock_on_element);
253 xr.setContentHandler(xmlTourHandler);
254
255 File tour_file = new File(xml_filename);
256 FileInputStream fis = new FileInputStream(tour_file);
257
258 InputSource is = new InputSource(fis);
259 xr.parse(is);
260
261 // get the HashMap List that results from parsing the file
262 hashmap_list = xmlTourHandler.getHashmapList();
263
264
265 } catch (Exception e) {
266 e.printStackTrace();
267 }
268
269 return hashmap_list;
270 }
271 public ArrayList<TipLocation> loadTour(String tour_filename)
272 {
273 ArrayList<HashMap<String,String>> location_hashmap_list
274 = parseXMLToHashMapArrayList(tour_filename,"Location");
275
276 if (location_hashmap_list != null) {
277 Log.d("TippleActivity::loadTour()", "XML Tour File Parsed");
278 }
279
280 ArrayList<TipLocation> locations = new ArrayList<TipLocation>();
281
282 for (int i=0; i<location_hashmap_list.size(); i++) {
283 HashMap<String,String> location_hashmap = location_hashmap_list.get(i);
284
285 TipLocation location = new TipLocation(location_hashmap);
286 locations.add(location);
287 }
288
289 return locations;
290 }
291
292 protected ArrayList<TipLocation> loadUserTrail(String log_filename)
293 {
294 ArrayList<HashMap<String,String>> logentry_hashmap_list
295 = parseXMLToHashMapArrayList(log_filename,"LogEntry");
296
297 ArrayList<TipLocation> locations = new ArrayList<TipLocation>();
298
299 if (logentry_hashmap_list != null) {
300 Log.d("TippleActivity::loadUserTrail()", "XML User Activity Log File Parsed");
301
302
303 for (int i=0; i<logentry_hashmap_list.size(); i++) {
304 HashMap<String,String> logentry_hashmap = logentry_hashmap_list.get(i);
305
306 HashMap<String,String> location_hashmap = new HashMap<String,String>();
307 location_hashmap.put("longitude",logentry_hashmap.get("longitude"));
308 location_hashmap.put("latitude",logentry_hashmap.get("latitude"));
309 location_hashmap.put("radius",logentry_hashmap.get("accuracy"));
310 location_hashmap.put("title",logentry_hashmap.get("action"));
311 location_hashmap.put("text",logentry_hashmap.get("message"));
312
313 TipLocation location = new TipLocation(location_hashmap);
314 locations.add(location);
315 }
316 }
317
318 return locations;
319 }
320
321
322 protected String SyncSynthesizeToFile(String text, String id, String root_utterance)
323 {
324 String audio_dir = TippleActivity.audioDirectory;
325 File tts_file = new File(audio_dir, id+"-"+root_utterance+"-TTS.wav");
326 String tts_filename = tts_file.getAbsolutePath();
327
328 if (tts_file.exists()) {
329 // already synthesized this
330 return tts_filename;
331 }
332
333 // Rendering the supplied text of the id+utterance derived WAV file
334 HashMap<String, String> hashRender = new HashMap<String, String>();
335 hashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, text);
336
337 String UTTERANCE = root_utterance+"-utterance";
338
339 hashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, UTTERANCE);
340 UtteranceWaitListener listener = new UtteranceWaitListener(UTTERANCE);
341 tts_.setOnUtteranceCompletedListener(listener);
342
343 tts_.synthesizeToFile(text, hashRender, tts_filename);
344
345 try {
346 listener.waitForComplete();
347 }
348 catch (Exception e) {
349 e.printStackTrace();
350 return null;
351 }
352
353 return tts_filename;
354 }
355
356 boolean genPrevVisited = true;
357
358 public boolean textToSpeechToLocation(TipLocation tip_location, boolean visited_previously)
359 {
360 if (genPrevVisited) {
361 prevVisitedFilename = SyncSynthesizeToFile("Previously visited.","Previously-visited","cue");
362 System.err.println("** Prev visisted file = " + prevVisitedFilename);
363 genPrevVisited = false;
364 }
365
366 String title = tip_location.getTitle();
367 String text = tip_location.getText();
368 String id = tip_location.getID();
369
370 String title_filename = SyncSynthesizeToFile(title,id,"title");
371 String text_filename = SyncSynthesizeToFile(text,id,"text");
372
373 if ((title_filename!=null) && (text_filename!=null)) {
374 String audio_dir = TippleActivity.audioDirectory;
375 File ding_file = new File(audio_dir, "DingExtended.wav");
376 String ding_filename = ding_file.getAbsolutePath();
377
378 if (audio_player_view_.addAudio(id)) {
379 TippleActivity.log.optMessage("Queue Audio",title);
380 audio_player_view_.queueAudio(title_filename,id,title,visited_previously);
381 audio_player_view_.queueAudio(text_filename,id,text);
382 audio_player_view_.queueAudio(ding_filename,id,"[Audio Bing]");
383
384 audio_player_view_.updateTextViewIfHeadIsNewLocation();
385 }
386 }
387
388 return true;
389 }
390
391
392 public static void stopOverlayThreads()
393 {
394 if (circlesOverlay!=null) {
395 circlesOverlay.stop();
396 circlesOverlay = null;
397 }
398
399 if (itemizedMarkerOverlay!=null) {
400 itemizedMarkerOverlay.stop();
401 itemizedMarkerOverlay = null;
402 }
403
404 if (routeOverlay!=null) {
405 routeOverlay.stop();
406 routeOverlay = null;
407 }
408
409 if (routeMarkerOverlay!=null) {
410 routeMarkerOverlay.stop();
411 routeMarkerOverlay = null;
412 }
413 }
414 private static class UtteranceWaitListener implements OnUtteranceCompletedListener {
415 private boolean mIsComplete = false;
416 private final String mExpectedUtterance;
417
418 public UtteranceWaitListener(String expectedUtteranceId) {
419 mExpectedUtterance = expectedUtteranceId;
420 }
421
422 public void onUtteranceCompleted(String utteranceId) {
423 if (mExpectedUtterance.equals(utteranceId)) {
424 synchronized(this) {
425 mIsComplete = true;
426 notify();
427 }
428 }
429 }
430
431 public boolean waitForComplete() throws InterruptedException {
432 if (mIsComplete) {
433 return true;
434 }
435
436 synchronized (this) {
437 int TTS_SPEECH_MAX_WAIT_TIME = 5* 1000;
438 wait(TTS_SPEECH_MAX_WAIT_TIME);
439 return mIsComplete;
440 }
441 }
442
443 }
444}
Note: See TracBrowser for help on using the repository browser.