Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2287 - 1

2
namespace GMap.NET
3
{
4
   using System;
5
   using System.Collections.Generic;
6
   using System.Diagnostics;
7
   using System.Globalization;
8
   using System.IO;
9
   using System.Net;
10
   using System.Text;
11
   using System.Threading;
12
   using System.Xml;
13
   using System.Xml.Serialization;
14
   using GMap.NET.CacheProviders;
15
   using GMap.NET.Internals;
16
   using GMap.NET.MapProviders;
17
    using System.Reflection;
18
 
19
#if PocketPC
20
   using OpenNETCF.ComponentModel;
21
   using OpenNETCF.Threading;
22
   using Thread=OpenNETCF.Threading.Thread2;
23
#endif
24
 
25
   /// <summary>
26
   /// maps manager
27
   /// </summary>
28
   public class GMaps : Singleton<GMaps>
29
   {
30
      /// <summary>
31
      /// tile access mode
32
      /// </summary>
33
      public AccessMode Mode = AccessMode.ServerAndCache;
34
 
35
      /// <summary>
36
      /// is map ussing cache for routing
37
      /// </summary>
38
      public bool UseRouteCache = true;
39
 
40
      /// <summary>
41
      /// is map using cache for geocoder
42
      /// </summary>
43
      public bool UseGeocoderCache = true;
44
 
45
      /// <summary>
46
      /// is map using cache for directions
47
      /// </summary>
48
      public bool UseDirectionsCache = true;
49
 
50
      /// <summary>
51
      /// is map using cache for placemarks
52
      /// </summary>
53
      public bool UsePlacemarkCache = true;
54
 
55
      /// <summary>
56
      /// is map ussing cache for other url
57
      /// </summary>
58
      public bool UseUrlCache = true;
59
 
60
      /// <summary>
61
      /// is map using memory cache for tiles
62
      /// </summary>
63
      public bool UseMemoryCache = true;
64
 
65
      /// <summary>
66
      /// primary cache provider, by default: ultra fast SQLite!
67
      /// </summary>
68
      public PureImageCache PrimaryCache
69
      {
70
         get
71
         {
72
            return Cache.Instance.ImageCache;
73
         }
74
         set
75
         {
76
            Cache.Instance.ImageCache = value;
77
         }
78
      }
79
 
80
      /// <summary>
81
      /// secondary cache provider, by default: none,
82
      /// use it if you have server in your local network
83
      /// </summary>
84
      public PureImageCache SecondaryCache
85
      {
86
         get
87
         {
88
            return Cache.Instance.ImageCacheSecond;
89
         }
90
         set
91
         {
92
            Cache.Instance.ImageCacheSecond = value;
93
         }
94
      }
95
 
96
      /// <summary>
97
      /// MemoryCache provider
98
      /// </summary>
99
      public readonly MemoryCache MemoryCache = new MemoryCache();
100
 
101
      /// <summary>
102
      /// load tiles in random sequence
103
      /// </summary>
104
      public bool ShuffleTilesOnLoad = false;
105
 
106
      /// <summary>
107
      /// tile queue to cache
108
      /// </summary>
109
      readonly Queue<CacheQueueItem> tileCacheQueue = new Queue<CacheQueueItem>();
110
 
111
      bool? isRunningOnMono;
112
 
113
      /// <summary>
114
      /// return true if running on mono
115
      /// </summary>
116
      /// <returns></returns>
117
      public bool IsRunningOnMono
118
      {
119
         get
120
         {
121
            if(!isRunningOnMono.HasValue)
122
            {
123
               try
124
               {
125
                  isRunningOnMono = (Type.GetType("Mono.Runtime") != null);
126
                  return isRunningOnMono.Value;
127
               }
128
               catch
129
               {
130
               }
131
            }
132
            else
133
            {
134
               return isRunningOnMono.Value;
135
            }
136
            return false;
137
         }
138
      }
139
 
140
      /// <summary>
141
      /// cache worker
142
      /// </summary>
143
      Thread CacheEngine;
144
 
145
      internal readonly AutoResetEvent WaitForCache = new AutoResetEvent(false);
146
 
147
#if !PocketPC
148
      static GMaps()
149
      {
150
          if (GMapProvider.TileImageProxy == null)
151
          {
152
              try
153
              {
154
                  AppDomain d = AppDomain.CurrentDomain;
155
                  var AssembliesLoaded = d.GetAssemblies();
156
 
157
                  Assembly l = null;
158
 
159
                  foreach (var a in AssembliesLoaded)
160
                  {
161
                      if (a.FullName.Contains("GMap.NET.WindowsForms") || a.FullName.Contains("GMap.NET.WindowsPresentation"))
162
                      {
163
                          l = a;
164
                          break;
165
                      }
166
                  }
167
 
168
                  if (l == null)
169
                  {
170
                      var jj = Assembly.GetExecutingAssembly().Location;
171
                      var hh = Path.GetDirectoryName(jj);
172
                      var f1 = hh + Path.DirectorySeparatorChar + "GMap.NET.WindowsForms.dll";
173
                      var f2 = hh + Path.DirectorySeparatorChar + "GMap.NET.WindowsPresentation.dll";
174
                      if (File.Exists(f1))
175
                      {
176
                          l = Assembly.LoadFile(f1);
177
                      }
178
                      else if (File.Exists(f2))
179
                      {
180
                          l = Assembly.LoadFile(f2);
181
                      }
182
                  }
183
 
184
                  if (l != null)
185
                  {
186
                      Type t = null;
187
 
188
                      if (l.FullName.Contains("GMap.NET.WindowsForms"))
189
                      {
190
                          t = l.GetType("GMap.NET.WindowsForms.GMapImageProxy");
191
                      }
192
                      else if (l.FullName.Contains("GMap.NET.WindowsPresentation"))
193
                      {
194
                          t = l.GetType("GMap.NET.WindowsPresentation.GMapImageProxy");
195
                      }
196
 
197
                      if (t != null)
198
                      {
199
                          t.InvokeMember("Enable", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, null);
200
                      }
201
                  }
202
              }
203
              catch (Exception ex)
204
              {
205
                  Debug.WriteLine("GMaps, try set TileImageProxy failed: " + ex.Message);
206
              }
207
          }
208
      }
209
#endif
210
 
211
      public GMaps()
212
      {
213
         #region singleton check
214
         if(Instance != null)
215
         {
216
            throw (new Exception("You have tried to create a new singleton class where you should have instanced it. Replace your \"new class()\" with \"class.Instance\""));
217
         }
218
         #endregion
219
 
220
         ServicePointManager.DefaultConnectionLimit = 5;
221
      }
222
 
223
#if !PocketPC
224
      /// <summary>
225
      /// triggers dynamic sqlite loading, 
226
      /// call this before you use sqlite for other reasons than caching maps
227
      /// </summary>
228
      public void SQLitePing()
229
      {
230
#if SQLite
231
#if !MONO
232
         SQLitePureImageCache.Ping();
233
#endif
234
#endif
235
      }
236
#endif
237
 
238
      #region -- Stuff --
239
 
240
#if !PocketPC
241
 
242
      /// <summary>
243
      /// exports current map cache to GMDB file
244
      /// if file exsist only new records will be added
245
      /// otherwise file will be created and all data exported
246
      /// </summary>
247
      /// <param name="file"></param>
248
      /// <returns></returns>
249
      public bool ExportToGMDB(string file)
250
      {
251
#if SQLite
252
         if(PrimaryCache is SQLitePureImageCache)
253
         {
254
            StringBuilder db = new StringBuilder((PrimaryCache as SQLitePureImageCache).GtileCache);
255
            db.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}Data.gmdb", GMapProvider.LanguageStr, Path.DirectorySeparatorChar);
256
 
257
            return SQLitePureImageCache.ExportMapDataToDB(db.ToString(), file);
258
         }
259
#endif
260
         return false;
261
      }
262
 
263
      /// <summary>
264
      /// imports GMDB file to current map cache
265
      /// only new records will be added
266
      /// </summary>
267
      /// <param name="file"></param>
268
      /// <returns></returns>
269
      public bool ImportFromGMDB(string file)
270
      {
271
#if SQLite
272
         if(PrimaryCache is GMap.NET.CacheProviders.SQLitePureImageCache)
273
         {
274
            StringBuilder db = new StringBuilder((PrimaryCache as SQLitePureImageCache).GtileCache);
275
            db.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}Data.gmdb", GMapProvider.LanguageStr, Path.DirectorySeparatorChar);
276
 
277
            return SQLitePureImageCache.ExportMapDataToDB(file, db.ToString());
278
         }
279
#endif
280
         return false;
281
      }
282
 
283
#if SQLite
284
 
285
      /// <summary>
286
      /// optimizes map database, *.gmdb
287
      /// </summary>
288
      /// <param name="file">database file name or null to optimize current user db</param>
289
      /// <returns></returns>
290
      public bool OptimizeMapDb(string file)
291
      {
292
         if(PrimaryCache is GMap.NET.CacheProviders.SQLitePureImageCache)
293
         {
294
            if(string.IsNullOrEmpty(file))
295
            {
296
               StringBuilder db = new StringBuilder((PrimaryCache as SQLitePureImageCache).GtileCache);
297
               db.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}Data.gmdb", GMapProvider.LanguageStr, Path.DirectorySeparatorChar);
298
 
299
               return SQLitePureImageCache.VacuumDb(db.ToString());
300
            }
301
            else
302
            {
303
               return SQLitePureImageCache.VacuumDb(file);
304
            }
305
         }
306
 
307
         return false;
308
      }
309
#endif
310
 
311
#endif
312
 
313
      /// <summary>
314
      /// enqueueens tile to cache
315
      /// </summary>
316
      /// <param name="task"></param>
317
      void EnqueueCacheTask(CacheQueueItem task)
318
      {
319
         lock(tileCacheQueue)
320
         {
321
            if(!tileCacheQueue.Contains(task))
322
            {
323
               Debug.WriteLine("EnqueueCacheTask: " + task);
324
 
325
               tileCacheQueue.Enqueue(task);
326
 
327
               if(CacheEngine != null && CacheEngine.IsAlive)
328
               {
329
                  WaitForCache.Set();
330
               }
331
#if PocketPC
332
               else if(CacheEngine == null || CacheEngine.State == ThreadState.Stopped || CacheEngine.State == ThreadState.Unstarted)
333
#else
334
               else if(CacheEngine == null || CacheEngine.ThreadState == System.Threading.ThreadState.Stopped || CacheEngine.ThreadState == System.Threading.ThreadState.Unstarted)
335
#endif
336
               {
337
                  CacheEngine = null;
338
                  CacheEngine = new Thread(new ThreadStart(CacheEngineLoop));
339
                  CacheEngine.Name = "CacheEngine";
340
                  CacheEngine.IsBackground = false;
341
                  CacheEngine.Priority = ThreadPriority.Lowest;
342
 
343
                  abortCacheLoop = false;
344
                  CacheEngine.Start();
345
               }
346
            }
347
         }
348
      }
349
 
350
      volatile bool abortCacheLoop = false;
351
      internal volatile bool noMapInstances = false;
352
 
353
      public TileCacheComplete OnTileCacheComplete;
354
      public TileCacheStart OnTileCacheStart;
355
      public TileCacheProgress OnTileCacheProgress;
356
 
357
      /// <summary>
358
      /// immediately stops background tile caching, call it if you want fast exit the process
359
      /// </summary>
360
      public void CancelTileCaching()
361
      {
362
         Debug.WriteLine("CancelTileCaching...");
363
 
364
         abortCacheLoop = true;
365
         lock(tileCacheQueue)
366
         {
367
            tileCacheQueue.Clear();
368
            WaitForCache.Set();
369
         }
370
      }
371
 
372
      int readingCache = 0;      
373
      volatile bool cacheOnIdleRead = true;
374
 
375
      /// <summary>
376
      /// delays writing tiles to cache while performing reads
377
      /// </summary>
378
      public bool CacheOnIdleRead
379
      {
380
          get
381
          {
382
              return cacheOnIdleRead;
383
          }
384
          set
385
          {
386
              cacheOnIdleRead = value;
387
          }
388
      }
389
 
390
      volatile bool boostCacheEngine = false;
391
 
392
      /// <summary>
393
      /// disables delay between saving tiles into database/cache
394
      /// </summary>
395
      public bool BoostCacheEngine
396
      {
397
          get
398
          {
399
              return boostCacheEngine;
400
          }
401
          set
402
          {
403
              boostCacheEngine = value;
404
          }
405
      }
406
 
407
      /// <summary>
408
      /// live for cache ;}
409
      /// </summary>
410
      /// <param name="sender"></param>
411
      /// <param name="e"></param>
412
      void CacheEngineLoop()
413
      {
414
         Debug.WriteLine("CacheEngine: start");
415
         int left = 0;
416
 
417
         if(OnTileCacheStart != null)
418
         {
419
            OnTileCacheStart();
420
         }
421
 
422
         bool startEvent = false;
423
 
424
         while(!abortCacheLoop)
425
         {
426
            try
427
            {
428
               CacheQueueItem? task = null;
429
 
430
               lock(tileCacheQueue)
431
               {
432
                  left = tileCacheQueue.Count;
433
                  if(left > 0)
434
                  {
435
                     task = tileCacheQueue.Dequeue();
436
                  }
437
               }
438
 
439
               if(task.HasValue)
440
               {
441
                  if(startEvent)
442
                  {
443
                     startEvent = false;
444
 
445
                     if(OnTileCacheStart != null)
446
                     {
447
                        OnTileCacheStart();
448
                     }
449
                  }
450
 
451
                  if(OnTileCacheProgress != null)
452
                  {
453
                     OnTileCacheProgress(left);
454
                  }
455
 
456
                  #region -- save --
457
                  // check if stream wasn't disposed somehow
458
                  if(task.Value.Img != null)
459
                  {
460
                     Debug.WriteLine("CacheEngine[" + left + "]: storing tile " + task.Value + ", " + task.Value.Img.Length / 1024 + "kB...");
461
 
462
                     if((task.Value.CacheType & CacheUsage.First) == CacheUsage.First && PrimaryCache != null)
463
                     {
464
                        if(cacheOnIdleRead)
465
                        {
466
                           while(Interlocked.Decrement(ref readingCache) > 0)
467
                           {
468
                              Thread.Sleep(1000);
469
                           }
470
                        }
471
                        PrimaryCache.PutImageToCache(task.Value.Img, task.Value.Tile.Type, task.Value.Tile.Pos, task.Value.Tile.Zoom);
472
                     }
473
 
474
                     if((task.Value.CacheType & CacheUsage.Second) == CacheUsage.Second && SecondaryCache != null)
475
                     {
476
                        if(cacheOnIdleRead)
477
                        {
478
                           while(Interlocked.Decrement(ref readingCache) > 0)
479
                           {
480
                              Thread.Sleep(1000);
481
                           }
482
                        }
483
                        SecondaryCache.PutImageToCache(task.Value.Img, task.Value.Tile.Type, task.Value.Tile.Pos, task.Value.Tile.Zoom);
484
                     }
485
 
486
                     task.Value.Clear();
487
 
488
                     if(!boostCacheEngine)
489
                     {
490
#if PocketPC
491
                        Thread.Sleep(3333);
492
#else
493
                        Thread.Sleep(333);
494
#endif
495
                     }
496
                  }
497
                  else
498
                  {
499
                     Debug.WriteLine("CacheEngineLoop: skip, tile disposed to early -> " + task.Value);
500
                  }
501
                  task = null;
502
                  #endregion
503
               }
504
               else
505
               {
506
                  if(!startEvent)
507
                  {
508
                     startEvent = true;
509
 
510
                     if(OnTileCacheComplete != null)
511
                     {
512
                        OnTileCacheComplete();
513
                     }
514
                  }
515
 
516
                  if(abortCacheLoop || noMapInstances || !WaitForCache.WaitOne(33333, false) || noMapInstances)
517
                  {
518
                     break;
519
                  }
520
               }
521
            }
522
#if !PocketPC
523
            catch(AbandonedMutexException)
524
            {
525
               break;
526
            }
527
#endif
528
            catch(Exception ex)
529
            {
530
               Debug.WriteLine("CacheEngineLoop: " + ex.ToString());
531
            }
532
         }
533
         Debug.WriteLine("CacheEngine: stop");
534
 
535
         if(!startEvent)
536
         {
537
            if(OnTileCacheComplete != null)
538
            {
539
               OnTileCacheComplete();
540
            }
541
         }
542
      }
543
 
544
      class StringWriterExt : StringWriter
545
      {
546
         public StringWriterExt(IFormatProvider info)
547
            : base(info)
548
         {
549
 
550
         }
551
 
552
         public override Encoding Encoding
553
         {
554
            get
555
            {
556
               return Encoding.UTF8;
557
            }
558
         }
559
      }
560
 
561
      public string SerializeGPX(gpxType targetInstance)
562
      {
563
         string retVal = string.Empty;
564
         using(StringWriterExt writer = new StringWriterExt(CultureInfo.InvariantCulture))
565
         {
566
            XmlSerializer serializer = new XmlSerializer(targetInstance.GetType());
567
            serializer.Serialize(writer, targetInstance);
568
            retVal = writer.ToString();
569
         }
570
         return retVal;
571
      }
572
 
573
      public gpxType DeserializeGPX(string objectXml)
574
      {
575
         gpxType retVal = null;
576
 
577
         using(StringReader stringReader = new StringReader(objectXml))
578
         {
579
            XmlTextReader xmlReader = new XmlTextReader(stringReader);
580
 
581
            XmlSerializer serializer = new XmlSerializer(typeof(gpxType));
582
            retVal = serializer.Deserialize(xmlReader) as gpxType;
583
 
584
            xmlReader.Close();
585
         }
586
         return retVal;
587
      }
588
 
589
      /// <summary>
590
      /// exports gps data to gpx file
591
      /// </summary>
592
      /// <param name="log">gps data</param>
593
      /// <param name="gpxFile">file to export</param>
594
      /// <returns>true if success</returns>
595
      public bool ExportGPX(IEnumerable<List<GpsLog>> log, string gpxFile)
596
      {
597
         try
598
         {
599
            gpxType gpx = new gpxType();
600
            {
601
               gpx.creator = "GMap.NET - http://greatmaps.codeplex.com";
602
               gpx.trk = new trkType[1];
603
               gpx.trk[0] = new trkType();
604
            }
605
 
606
            var sessions = new List<List<GpsLog>>(log);
607
            gpx.trk[0].trkseg = new trksegType[sessions.Count];
608
 
609
            int sesid = 0;
610
 
611
            foreach(var session in sessions)
612
            {
613
               trksegType seg = new trksegType();
614
               {
615
                  seg.trkpt = new wptType[session.Count];
616
               }
617
               gpx.trk[0].trkseg[sesid++] = seg;
618
 
619
               for(int i = 0; i < session.Count; i++)
620
               {
621
                  var point = session[i];
622
 
623
                  wptType t = new wptType();
624
                  {
625
                     #region -- set values --
626
                     t.lat = new decimal(point.Position.Lat);
627
                     t.lon = new decimal(point.Position.Lng);
628
 
629
                     t.time = point.TimeUTC;
630
                     t.timeSpecified = true;
631
 
632
                     if(point.FixType != FixType.Unknown)
633
                     {
634
                        t.fix = (point.FixType == FixType.XyD ? fixType.Item2d : fixType.Item3d);
635
                        t.fixSpecified = true;
636
                     }
637
 
638
                     if(point.SeaLevelAltitude.HasValue)
639
                     {
640
                        t.ele = new decimal(point.SeaLevelAltitude.Value);
641
                        t.eleSpecified = true;
642
                     }
643
 
644
                     if(point.EllipsoidAltitude.HasValue)
645
                     {
646
                        t.geoidheight = new decimal(point.EllipsoidAltitude.Value);
647
                        t.geoidheightSpecified = true;
648
                     }
649
 
650
                     if(point.VerticalDilutionOfPrecision.HasValue)
651
                     {
652
                        t.vdopSpecified = true;
653
                        t.vdop = new decimal(point.VerticalDilutionOfPrecision.Value);
654
                     }
655
 
656
                     if(point.HorizontalDilutionOfPrecision.HasValue)
657
                     {
658
                        t.hdopSpecified = true;
659
                        t.hdop = new decimal(point.HorizontalDilutionOfPrecision.Value);
660
                     }
661
 
662
                     if(point.PositionDilutionOfPrecision.HasValue)
663
                     {
664
                        t.pdopSpecified = true;
665
                        t.pdop = new decimal(point.PositionDilutionOfPrecision.Value);
666
                     }
667
 
668
                     if(point.SatelliteCount.HasValue)
669
                     {
670
                        t.sat = point.SatelliteCount.Value.ToString();
671
                     }
672
                     #endregion
673
                  }
674
                  seg.trkpt[i] = t;
675
               }
676
            }
677
            sessions.Clear();
678
 
679
#if !PocketPC
680
            File.WriteAllText(gpxFile, SerializeGPX(gpx), Encoding.UTF8);
681
#else
682
            using(StreamWriter w = File.CreateText(gpxFile))
683
            {
684
               w.Write(SerializeGPX(gpx));
685
               w.Close();
686
            }
687
#endif
688
         }
689
         catch(Exception ex)
690
         {
691
            Debug.WriteLine("ExportGPX: " + ex.ToString());
692
            return false;
693
         }
694
         return true;
695
      }
696
 
697
      #endregion
698
 
699
      /// <summary>
700
      /// gets image from tile server
701
      /// </summary>
702
      /// <param name="provider"></param>
703
      /// <param name="pos"></param>
704
      /// <param name="zoom"></param>
705
      /// <returns></returns>
706
      public PureImage GetImageFrom(GMapProvider provider, GPoint pos, int zoom, out Exception result)
707
      {
708
         PureImage ret = null;
709
         result = null;
710
 
711
         try
712
         {
713
            var rtile = new RawTile(provider.DbId, pos, zoom);
714
 
715
            // let't check memmory first
716
            if(UseMemoryCache)
717
            {
718
               var m = MemoryCache.GetTileFromMemoryCache(rtile);
719
               if(m != null)
720
               {
721
                  if(GMapProvider.TileImageProxy != null)
722
                  {
723
                     ret = GMapProvider.TileImageProxy.FromArray(m);
724
                     if(ret == null)
725
                     {
726
#if DEBUG
727
                        Debug.WriteLine("Image disposed in MemoryCache o.O, should never happen ;} " + new RawTile(provider.DbId, pos, zoom));
728
                        if(Debugger.IsAttached)
729
                        {
730
                           Debugger.Break();
731
                        }
732
#endif
733
                        m = null;
734
                     }
735
                  }
736
               }
737
            }
738
 
739
            if(ret == null)
740
            {
741
               if(Mode != AccessMode.ServerOnly && !provider.BypassCache)
742
               {
743
                  if(PrimaryCache != null)
744
                  {
745
                     // hold writer for 5s
746
                     if(cacheOnIdleRead)
747
                     {
748
                        Interlocked.Exchange(ref readingCache, 5);
749
                     }
750
 
751
                     ret = PrimaryCache.GetImageFromCache(provider.DbId, pos, zoom);
752
                     if(ret != null)
753
                     {
754
                        if(UseMemoryCache)
755
                        {
756
                           MemoryCache.AddTileToMemoryCache(rtile, ret.Data.GetBuffer());
757
                        }
758
                        return ret;
759
                     }
760
                  }
761
 
762
                  if(SecondaryCache != null)
763
                  {
764
                     // hold writer for 5s
765
                     if(cacheOnIdleRead)
766
                     {
767
                        Interlocked.Exchange(ref readingCache, 5);
768
                     }
769
 
770
                     ret = SecondaryCache.GetImageFromCache(provider.DbId, pos, zoom);
771
                     if(ret != null)
772
                     {
773
                        if(UseMemoryCache)
774
                        {
775
                           MemoryCache.AddTileToMemoryCache(rtile, ret.Data.GetBuffer());
776
                        }
777
                        EnqueueCacheTask(new CacheQueueItem(rtile, ret.Data.GetBuffer(), CacheUsage.First));
778
                        return ret;
779
                     }
780
                  }
781
               }
782
 
783
               if(Mode != AccessMode.CacheOnly)
784
               {
785
                  ret = provider.GetTileImage(pos, zoom);
786
                  {
787
                     // Enqueue Cache
788
                     if(ret != null)
789
                     {
790
                        if(UseMemoryCache)
791
                        {
792
                           MemoryCache.AddTileToMemoryCache(rtile, ret.Data.GetBuffer());
793
                        }
794
 
795
                        if (Mode != AccessMode.ServerOnly && !provider.BypassCache)
796
                        {
797
                           EnqueueCacheTask(new CacheQueueItem(rtile, ret.Data.GetBuffer(), CacheUsage.Both));
798
                        }
799
                     }
800
                  }
801
               }
802
               else
803
               {
804
                  result = noDataException;
805
               }
806
            }
807
         }
808
         catch(Exception ex)
809
         {
810
            result = ex;
811
            ret = null;
812
            Debug.WriteLine("GetImageFrom: " + ex.ToString());
813
         }
814
 
815
         return ret;
816
      }
817
 
818
      readonly Exception noDataException = new Exception("No data in local tile cache...");
819
 
820
#if !PocketPC
821
      TileHttpHost host;
822
 
823
      /// <summary>
824
      /// turns on tile host
825
      /// </summary>
826
      /// <param name="port"></param>
827
      public void EnableTileHost(int port)
828
      {
829
         if(host == null)
830
         {
831
            host = new TileHttpHost();
832
         }
833
         host.Start(port);
834
      }
835
 
836
      /// <summary>
837
      /// turns off tile host
838
      /// </summary>
839
      /// <param name="port"></param>
840
      public void DisableTileHost()
841
      {
842
          if (host != null)
843
          {
844
              host.Stop();
845
          }
846
      }
847
#endif
848
   }
849
}