]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/function/AsyncMediaLoader.java
Version 17.2, February 2015
[GpsPrune.git] / tim / prune / function / AsyncMediaLoader.java
1 package tim.prune.function;
2
3 import java.io.File;
4
5 import tim.prune.App;
6 import tim.prune.DataSubscriber;
7 import tim.prune.GenericFunction;
8 import tim.prune.I18nManager;
9 import tim.prune.UpdateMessageBroker;
10 import tim.prune.data.AudioClip;
11 import tim.prune.data.DataPoint;
12 import tim.prune.data.Distance;
13 import tim.prune.data.MediaObject;
14 import tim.prune.data.Photo;
15 import tim.prune.data.Track;
16 import tim.prune.data.UnitSetLibrary;
17 import tim.prune.load.MediaHelper;
18 import tim.prune.load.MediaLoadProgressDialog;
19 import tim.prune.undo.UndoLoadAudios;
20 import tim.prune.undo.UndoLoadPhotos;
21
22 /**
23  * Function to load media asynchronously,
24  * either from inside a zip/kmz file or remotely
25  */
26 public class AsyncMediaLoader extends GenericFunction
27 implements Runnable, Cancellable
28 {
29         /** Archive from which points were loaded */
30         private File _zipFile = null;
31         /** Array of links */
32         private String[] _linkArray = null;
33         /** Track to use for connecting */
34         private Track _track = null;
35         /** Source file */
36         private File _sourceFile = null;
37         /** Cancelled flag */
38         private boolean _cancelled = false;
39
40
41         /**
42          * Constructor
43          * @param inApp App object
44          * @param inLinkArray array of links
45          * @param inTrack Track object for connecting points
46          * @param inSourceFile file from which data was loaded, if any
47          */
48         public AsyncMediaLoader(App inApp, File inZipFile, String[] inLinkArray, Track inTrack, File inSourceFile)
49         {
50                 super(inApp);
51                 _zipFile = inZipFile;
52                 _linkArray = inLinkArray;
53                 _track = inTrack;
54                 _sourceFile = inSourceFile;
55         }
56
57         /**
58          * Begin the load
59          */
60         public void begin()
61         {
62                 _cancelled = false;
63                 if (_linkArray != null)
64                         new Thread(this).start();
65         }
66
67         /** Cancel */
68         public void cancel() {
69                 _cancelled = true;
70         }
71
72         /**
73          * @return the name key
74          */
75         public String getNameKey() {
76                 return "function.asyncmediaload";
77         }
78
79         /**
80          * Execute the load in a separate thread
81          */
82         public void run()
83         {
84                 // Count links first so that progress bar can be shown
85                 int numLinks = 0;
86                 for (int i=0; i<_linkArray.length; i++) {
87                         if (_linkArray[i] != null) {
88                                 numLinks++;
89                         }
90                 }
91                 if (numLinks <= 0) return;
92                 // Make progress dialog
93                 MediaLoadProgressDialog progressDialog = new MediaLoadProgressDialog(_app.getFrame(), this);
94
95                 // Make array to store results
96                 MediaObject[] media = new MediaObject[numLinks];
97                 int currLink = 0;
98                 for (int i=0; i<_linkArray.length && !_cancelled; i++)
99                 {
100                         if (_linkArray[i] != null)
101                         {
102                                 MediaObject mf = MediaHelper.createMediaObject(_zipFile, _linkArray[i], _sourceFile);
103                                 if (mf != null)
104                                 {
105                                         // Check if the media object has a point now (from exif)
106                                         DataPoint exifPoint = mf.getDataPoint();
107                                         // attach media to point and set status
108                                         _track.getPoint(i).attachMedia(mf);
109                                         // Check exif to see whether media was already tagged
110                                         final MediaObject.Status originalMediaStatus =
111                                                 (exifPoint == null ? MediaObject.Status.NOT_CONNECTED : MediaObject.Status.TAGGED);
112                                         mf.setOriginalStatus(originalMediaStatus);
113                                         MediaObject.Status currMediaStatus = MediaObject.Status.TAGGED;
114                                         if (exifPoint != null)
115                                         {
116                                                 final double distinMetres = Distance.convertRadiansToDistance(
117                                                         DataPoint.calculateRadiansBetween(exifPoint, _track.getPoint(i)),
118                                                         UnitSetLibrary.UNITS_METRES);
119                                                 if (distinMetres > 10.0) {
120                                                         currMediaStatus = MediaObject.Status.CONNECTED; // still connected but changed
121                                                 }
122                                         }
123                                         mf.setCurrentStatus(currMediaStatus);
124                                         media[currLink] = mf;
125                                         // update progress
126                                         if (!_app.isBusyLoading()) {
127                                                 progressDialog.showProgress(currLink, numLinks);
128                                         }
129                                         currLink++;
130                                 }
131                                 try {Thread.sleep(100);} catch (InterruptedException ie) {}
132                         }
133                 }
134                 progressDialog.close();
135
136                 // Wait until App is ready to receive media (may have to ask about append/replace etc)
137                 waitUntilAppReady();
138
139                 // Go through the loaded media and check if the points are still in the track
140                 int numPhotos = 0, numAudios = 0;
141                 for (currLink=0; currLink<numLinks; currLink++)
142                 {
143                         MediaObject mo = media[currLink];
144                         if (mo != null && _track.containsPoint(mo.getDataPoint()))
145                         {
146                                 if (mo instanceof Photo)
147                                 {
148                                         _app.getTrackInfo().getPhotoList().addPhoto((Photo) mo);
149                                         numPhotos++;
150                                 }
151                                 else if (mo instanceof AudioClip)
152                                 {
153                                         _app.getTrackInfo().getAudioList().addAudio((AudioClip) mo);
154                                         numAudios++;
155                                 }
156                         }
157                 }
158                 // Confirm and update
159                 if (numPhotos > 0) {
160                         _app.completeFunction(new UndoLoadPhotos(numPhotos, 0), "" + numPhotos + " " +
161                                 I18nManager.getText(numPhotos == 1?"confirm.jpegload.single":"confirm.jpegload.multi"));
162                 }
163                 if (numAudios > 0) {
164                         _app.completeFunction(new UndoLoadAudios(numAudios), I18nManager.getText("confirm.audioload"));
165                 }
166                 UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_ADDED_OR_REMOVED);
167         }
168
169
170         /**
171          * Wait until the App is ready
172          */
173         private void waitUntilAppReady()
174         {
175                 long waitInterval = 500; // milliseconds
176                 while (_app.isBusyLoading())
177                 {
178                         try {Thread.sleep(waitInterval);} catch (InterruptedException ie) {}
179                         waitInterval *= 1.2;
180                 }
181         }
182 }