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;
}
}
}