]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - src/tim/prune/function/AsyncMediaLoader.java
Moved source into separate src directory due to popular request
[GpsPrune.git] / src / tim / prune / function / AsyncMediaLoader.java
diff --git a/src/tim/prune/function/AsyncMediaLoader.java b/src/tim/prune/function/AsyncMediaLoader.java
new file mode 100644 (file)
index 0000000..78ffc83
--- /dev/null
@@ -0,0 +1,182 @@
+package tim.prune.function;
+
+import java.io.File;
+
+import tim.prune.App;
+import tim.prune.DataSubscriber;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.AudioClip;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Distance;
+import tim.prune.data.MediaObject;
+import tim.prune.data.Photo;
+import tim.prune.data.Track;
+import tim.prune.data.UnitSetLibrary;
+import tim.prune.load.MediaHelper;
+import tim.prune.load.MediaLoadProgressDialog;
+import tim.prune.undo.UndoLoadAudios;
+import tim.prune.undo.UndoLoadPhotos;
+
+/**
+ * Function to load media asynchronously,
+ * either from inside a zip/kmz file or remotely
+ */
+public class AsyncMediaLoader extends GenericFunction
+implements Runnable, Cancellable
+{
+       /** Archive from which points were loaded */
+       private File _zipFile = null;
+       /** Array of links */
+       private String[] _linkArray = null;
+       /** Track to use for connecting */
+       private Track _track = null;
+       /** Source file */
+       private File _sourceFile = null;
+       /** Cancelled flag */
+       private boolean _cancelled = false;
+
+
+       /**
+        * Constructor
+        * @param inApp App object
+        * @param inLinkArray array of links
+        * @param inTrack Track object for connecting points
+        * @param inSourceFile file from which data was loaded, if any
+        */
+       public AsyncMediaLoader(App inApp, File inZipFile, String[] inLinkArray, Track inTrack, File inSourceFile)
+       {
+               super(inApp);
+               _zipFile = inZipFile;
+               _linkArray = inLinkArray;
+               _track = inTrack;
+               _sourceFile = inSourceFile;
+       }
+
+       /**
+        * Begin the load
+        */
+       public void begin()
+       {
+               _cancelled = false;
+               if (_linkArray != null)
+                       new Thread(this).start();
+       }
+
+       /** Cancel */
+       public void cancel() {
+               _cancelled = true;
+       }
+
+       /**
+        * @return the name key
+        */
+       public String getNameKey() {
+               return "function.asyncmediaload";
+       }
+
+       /**
+        * Execute the load in a separate thread
+        */
+       public void run()
+       {
+               // Count links first so that progress bar can be shown
+               int numLinks = 0;
+               for (int i=0; i<_linkArray.length; i++) {
+                       if (_linkArray[i] != null) {
+                               numLinks++;
+                       }
+               }
+               if (numLinks <= 0) return;
+               // Make progress dialog
+               MediaLoadProgressDialog progressDialog = new MediaLoadProgressDialog(_app.getFrame(), this);
+
+               // Make array to store results
+               MediaObject[] media = new MediaObject[numLinks];
+               int currLink = 0;
+               for (int i=0; i<_linkArray.length && !_cancelled; i++)
+               {
+                       if (_linkArray[i] != null)
+                       {
+                               MediaObject mf = MediaHelper.createMediaObject(_zipFile, _linkArray[i], _sourceFile);
+                               if (mf != null)
+                               {
+                                       // Check if the media object has a point now (from exif)
+                                       DataPoint exifPoint = mf.getDataPoint();
+                                       // attach media to point and set status
+                                       _track.getPoint(i).attachMedia(mf);
+                                       // Check exif to see whether media was already tagged
+                                       final MediaObject.Status originalMediaStatus =
+                                               (exifPoint == null ? MediaObject.Status.NOT_CONNECTED : MediaObject.Status.TAGGED);
+                                       mf.setOriginalStatus(originalMediaStatus);
+                                       MediaObject.Status currMediaStatus = MediaObject.Status.TAGGED;
+                                       if (exifPoint != null)
+                                       {
+                                               final double distinMetres = Distance.convertRadiansToDistance(
+                                                       DataPoint.calculateRadiansBetween(exifPoint, _track.getPoint(i)),
+                                                       UnitSetLibrary.UNITS_METRES);
+                                               if (distinMetres > 10.0) {
+                                                       currMediaStatus = MediaObject.Status.CONNECTED; // still connected but changed
+                                               }
+                                       }
+                                       mf.setCurrentStatus(currMediaStatus);
+                                       media[currLink] = mf;
+                                       // update progress
+                                       if (!_app.isBusyLoading()) {
+                                               progressDialog.showProgress(currLink, numLinks);
+                                       }
+                                       currLink++;
+                               }
+                               try {Thread.sleep(100);} catch (InterruptedException ie) {}
+                       }
+               }
+               progressDialog.close();
+
+               // Wait until App is ready to receive media (may have to ask about append/replace etc)
+               waitUntilAppReady();
+
+               // Go through the loaded media and check if the points are still in the track
+               int numPhotos = 0, numAudios = 0;
+               for (currLink=0; currLink<numLinks; currLink++)
+               {
+                       MediaObject mo = media[currLink];
+                       if (mo != null && _track.containsPoint(mo.getDataPoint()))
+                       {
+                               if (mo instanceof Photo)
+                               {
+                                       _app.getTrackInfo().getPhotoList().addPhoto((Photo) mo);
+                                       numPhotos++;
+                               }
+                               else if (mo instanceof AudioClip)
+                               {
+                                       _app.getTrackInfo().getAudioList().addAudio((AudioClip) mo);
+                                       numAudios++;
+                               }
+                       }
+               }
+               // Confirm and update
+               if (numPhotos > 0) {
+                       _app.completeFunction(new UndoLoadPhotos(numPhotos, 0), "" + numPhotos + " " +
+                               I18nManager.getText(numPhotos == 1?"confirm.jpegload.single":"confirm.jpegload.multi"));
+               }
+               if (numAudios > 0) {
+                       _app.completeFunction(new UndoLoadAudios(numAudios), I18nManager.getText("confirm.audioload"));
+               }
+               UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_ADDED_OR_REMOVED);
+       }
+
+
+       /**
+        * Wait until the App is ready
+        */
+       private void waitUntilAppReady()
+       {
+               long waitInterval = 500; // milliseconds
+               while (_app.isBusyLoading())
+               {
+                       try {Thread.sleep(waitInterval);} catch (InterruptedException ie) {}
+                       waitInterval *= 1.2;
+               }
+       }
+}