diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index b93ad0eaf4..768f63f610 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -9,6 +9,7 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
+ Not selected
Recorder Split
Use Recorder Split
Rewrite clips when used space exceeds the storage size
diff --git a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteMenuController.java b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteMenuController.java
index fb4022e688..758934f710 100644
--- a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteMenuController.java
+++ b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteMenuController.java
@@ -50,7 +50,7 @@ public class AudioVideoNoteMenuController extends MenuController {
@Override
public void onClick(DialogInterface dialog, int which) {
if (plugin != null) {
- plugin.deleteRecording(getRecording());
+ plugin.deleteRecording(getRecording(), true);
getMapActivity().getContextMenu().close();
}
}
diff --git a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteRecordingMenu.java b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteRecordingMenu.java
index 054a028d01..5d9a331c50 100644
--- a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteRecordingMenu.java
+++ b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNoteRecordingMenu.java
@@ -2,6 +2,7 @@ package net.osmand.plus.audionotes;
import android.os.Handler;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
@@ -118,6 +119,7 @@ public class AudioVideoNoteRecordingMenu {
}
public void hide() {
+ stopCounter();
view.setVisibility(View.GONE);
plugin.stopCamera();
viewfinder.removeAllViews();
@@ -169,16 +171,34 @@ public class AudioVideoNoteRecordingMenu {
centerButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- rec(plugin.getMapActivity());
+ rec(plugin.getMapActivity(), false);
}
});
applyViewfinderVisibility();
}
+ public boolean restartRecordingIfNeeded() {
+ boolean restart = false;
+ CurrentRecording recording = plugin.getCurrentRecording();
+ if (recording != null
+ && recording.getType() == AVActionType.REC_VIDEO
+ && plugin.AV_RECORDER_SPLIT.get()) {
+ int clipLength = plugin.AV_RS_CLIP_LENGTH.get() * 60;
+ int duration = (int) ((System.currentTimeMillis() - startTime) / 1000);
+ restart = duration >= clipLength;
+ if (restart) {
+ rec(getMapActivity(), true);
+ }
+ }
+ return restart;
+ }
+
public void updateDuration() {
- TextView timeText = (TextView) view.findViewById(R.id.timeText);
- int duration = (int) ((System.currentTimeMillis() - startTime) / 1000);
- timeText.setText(Algorithms.formatDuration(duration));
+ if (plugin.getCurrentRecording() != null) {
+ TextView timeText = (TextView) view.findViewById(R.id.timeText);
+ int duration = (int) ((System.currentTimeMillis() - startTime) / 1000);
+ timeText.setText(Algorithms.formatDuration(duration));
+ }
}
protected void applyViewfinderVisibility() {
@@ -236,21 +256,30 @@ public class AudioVideoNoteRecordingMenu {
return res;
}
- public void rec(final MapActivity mapActivity) {
+ public void rec(final MapActivity mapActivity, final boolean restart) {
stopCounter();
+ final CurrentRecording recording = plugin.getCurrentRecording();
+ int delay;
+ if (recording != null && recording.getType() == AVActionType.REC_PHOTO) {
+ delay = 200;
+ } else {
+ delay = 1;
+ }
handler.postDelayed(new Runnable() {
@Override
public void run() {
- CurrentRecording recording = plugin.getCurrentRecording();
if (recording != null) {
if (recording.getType() == AVActionType.REC_PHOTO) {
plugin.shoot();
} else {
- plugin.stopRecording(mapActivity);
+ plugin.stopRecording(mapActivity, restart);
+ if (restart) {
+ startCounter();
+ }
}
}
}
- }, 200);
+ }, delay);
}
public void recExternal(final MapActivity mapActivity) {
@@ -270,7 +299,7 @@ public class AudioVideoNoteRecordingMenu {
private void startCounter() {
startTime = System.currentTimeMillis();
-
+ Log.e("111", "START");
if (recTimer != null) {
recTimer.cancel();
}
@@ -282,7 +311,9 @@ public class AudioVideoNoteRecordingMenu {
handler.post(new Runnable() {
@Override
public void run() {
- updateDuration();
+ if (!restartRecordingIfNeeded()) {
+ updateDuration();
+ }
}
});
}
@@ -291,6 +322,7 @@ public class AudioVideoNoteRecordingMenu {
}
private void stopCounter() {
+ Log.e("111", "STOP");
if (recTimer != null) {
recTimer.cancel();
recTimer = null;
diff --git a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java
index 038b9c0b87..e13bb70df9 100644
--- a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java
+++ b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java
@@ -21,6 +21,7 @@ import android.media.MediaRecorder;
import android.media.SoundPool;
import android.net.Uri;
import android.os.Build;
+import android.os.StatFs;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.view.Display;
@@ -72,10 +73,12 @@ import org.apache.commons.logging.Log;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.text.DateFormat;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
@@ -782,7 +785,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
@Override
public void mapActivityScreenOff(MapActivity activity) {
- stopCameraRecording(activity);
+ stopRecording(activity, false);
}
@Override
@@ -803,7 +806,13 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
finishPhotoRecording(false);
} else {
activity.getContextMenu().close();
- stopRecording(activity);
+ if (currentRecording.getType() == AVActionType.REC_VIDEO && AV_RECORDER_SPLIT.get()) {
+ runAction = AV_DEFAULT_ACTION_VIDEO;
+ LatLon latLon = getNextRecordingLocation();
+ actionLat = latLon.getLatitude();
+ actionLon = latLon.getLongitude();
+ }
+ stopRecording(activity, false);
}
finishRecording();
}
@@ -854,21 +863,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public void recordVideoCamera(final double lat, final double lon, final MapActivity mapActivity) {
final CamcorderProfile p = CamcorderProfile.get(AV_VIDEO_QUALITY.get());
- final Camera.Size mPreviewSize;
- if (mSupportedPreviewSizes != null) {
- int width;
- int height;
- if (recordingMenu.isLandscapeLayout()) {
- width = p.videoFrameWidth;
- height = p.videoFrameHeight;
- } else {
- height = p.videoFrameWidth;
- width = p.videoFrameHeight;
- }
- mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
- } else {
- mPreviewSize = null;
- }
+ final Camera.Size mPreviewSize = getPreviewSize();
final SurfaceView view;
if (mPreviewSize != null) {
@@ -888,23 +883,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
MediaRecorder mr = new MediaRecorder();
try {
- Parameters parameters = cam.getParameters();
-
- // camera focus type
- List sfm = parameters.getSupportedFocusModes();
- if (sfm.contains("continuous-video")) {
- parameters.setFocusMode("continuous-video");
- }
-
- int cameraOrientation = getCamOrientation(mapActivity, Camera.CameraInfo.CAMERA_FACING_BACK);
- cam.setDisplayOrientation(cameraOrientation);
- parameters.set("rotation", cameraOrientation);
- if (mPreviewSize != null) {
- parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
- }
- cam.setParameters(parameters);
- cam.setPreviewDisplay(holder);
- cam.startPreview();
+ startCamera(mPreviewSize, holder);
cam.unlock();
mr.setCamera(cam);
@@ -917,27 +896,12 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
return;
}
-
- String ext = MPEG4_EXTENSION;
-// if (AV_VIDEO_FORMAT.get() == VIDEO_OUTPUT_3GP) {
-// ext = THREEGP_EXTENSION;
-// }
- final File f = getBaseFileName(lat, lon, app, ext);
-
- mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
- mr.setVideoSource(MediaRecorder.VideoSource.CAMERA);
-// if (AV_VIDEO_FORMAT.get() == VIDEO_OUTPUT_3GP) {
-// mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
-// } else {
-// mr.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
-// }
-
- giveMediaRecorderHintRotatedScreen(mapActivity, mr);
- //mr.setPreviewDisplay(holder.getSurface());
-
- mr.setProfile(p);
- mr.setOutputFile(f.getAbsolutePath());
+ final File f = getBaseFileName(lat, lon, app, MPEG4_EXTENSION);
+ initMediaRecorder(mr, p, f);
try {
+ if (AV_RECORDER_SPLIT.get()) {
+ cleanupSpace();
+ }
runMediaRecorder(mapActivity, mr, f);
} catch (Exception e) {
logErr(e);
@@ -951,6 +915,17 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
recordingMenu.show();
}
+ private void initMediaRecorder(MediaRecorder mr, CamcorderProfile p, File f) {
+ mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
+ mr.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+
+ giveMediaRecorderHintRotatedScreen(mapActivity, mr);
+ //mr.setPreviewDisplay(holder.getSurface());
+
+ mr.setProfile(p);
+ mr.setOutputFile(f.getAbsolutePath());
+ }
+
private void giveMediaRecorderHintRotatedScreen(final MapActivity mapActivity, final MediaRecorder mr) {
if (Build.VERSION.SDK_INT >= 9) {
try {
@@ -1013,6 +988,48 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
mapActivity.setRequestedOrientation(requestedOrientation);
}
+ private Camera.Size getPreviewSize() {
+ final CamcorderProfile p = CamcorderProfile.get(AV_VIDEO_QUALITY.get());
+ final Camera.Size mPreviewSize;
+ if (mSupportedPreviewSizes != null) {
+ int width;
+ int height;
+ if (recordingMenu.isLandscapeLayout()) {
+ width = p.videoFrameWidth;
+ height = p.videoFrameHeight;
+ } else {
+ height = p.videoFrameWidth;
+ width = p.videoFrameHeight;
+ }
+ mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
+ } else {
+ mPreviewSize = null;
+ }
+ return mPreviewSize;
+ }
+
+ protected void startCamera(Camera.Size mPreviewSize, SurfaceHolder holder) throws IOException {
+ Parameters parameters = cam.getParameters();
+
+ // camera focus type
+ List sfm = parameters.getSupportedFocusModes();
+ if (sfm.contains("continuous-video")) {
+ parameters.setFocusMode("continuous-video");
+ }
+
+ int cameraOrientation = getCamOrientation(mapActivity, Camera.CameraInfo.CAMERA_FACING_BACK);
+ cam.setDisplayOrientation(cameraOrientation);
+ parameters.set("rotation", cameraOrientation);
+ if (mPreviewSize != null) {
+ parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+ }
+ cam.setParameters(parameters);
+ if (holder != null) {
+ cam.setPreviewDisplay(holder);
+ }
+ cam.startPreview();
+ }
+
protected void stopCamera() {
try {
if (cam != null) {
@@ -1027,18 +1044,44 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
}
- private void stopCameraRecording(final MapActivity mapActivity) {
+ private boolean stopCameraRecording(boolean restart) {
+ boolean res = true;
if (mediaRec != null) {
mediaRec.stop();
+ AVActionType type = currentRecording.type;
+ indexFile(true, mediaRecFile);
mediaRec.release();
mediaRec = null;
- indexFile(true, mediaRecFile);
mediaRecFile = null;
- stopCamera();
- }
- if (recordControl != null) {
- setRecordListener(recordControl, mapActivity);
+
+ if (restart) {
+ try {
+ cam.lock();
+ if (AV_RECORDER_SPLIT.get()) {
+ cleanupSpace();
+ }
+
+ currentRecording = new CurrentRecording(type);
+ MediaRecorder mr = new MediaRecorder();
+ LatLon latLon = getNextRecordingLocation();
+ final File f = getBaseFileName(latLon.getLatitude(), latLon.getLongitude(), app, MPEG4_EXTENSION);
+
+ cam.unlock();
+ mr.setCamera(cam);
+ initMediaRecorder(mr, CamcorderProfile.get(AV_VIDEO_QUALITY.get()), f);
+ mr.prepare();
+ mr.start();
+ mediaRec = mr;
+ mediaRecFile = f;
+
+ } catch (Exception e) {
+ AccessibleToast.makeText(app, e.getMessage(), Toast.LENGTH_LONG).show();
+ e.printStackTrace();
+ res = false;
+ }
+ }
}
+ return res;
}
public void recordAudio(double lat, double lon, final MapActivity mapActivity) {
@@ -1162,6 +1205,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
parameters.setGpsLatitude(lat);
parameters.setGpsLongitude(lon);
parameters.setGpsProcessingMethod(locProvider.toUpperCase());
+ parameters.setGpsTimestamp(System.currentTimeMillis() / 1000);
}
switch (AV_CAMERA_FOCUS_TYPE.get()) {
case AV_CAMERA_FOCUS_HIPERFOCAL:
@@ -1353,6 +1397,69 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
}
+ private void cleanupSpace() {
+ File[] files = app.getAppPath(IndexConstants.AV_INDEX_DIR).listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String filename) {
+ return filename.endsWith("." + MPEG4_EXTENSION);
+ }
+ });
+
+ if (files != null) {
+ double usedSpace = 0;
+ for (File f : files) {
+ usedSpace += f.length();
+ }
+ usedSpace /= (1 << 30); // gigabytes
+
+ final CamcorderProfile p = CamcorderProfile.get(AV_VIDEO_QUALITY.get());
+ double bitrate = (((p.videoBitRate + p.audioBitRate) / 8f) * 60f) / (1 << 30); // gigabytes per minute
+ double clipSpace = bitrate * AV_RS_CLIP_LENGTH.get();
+ double storageSize = AV_RS_STORAGE_SIZE.get();
+
+ double availableSpace = storageSize;
+ File dir = app.getAppPath("").getParentFile();
+ if (dir.canRead()) {
+ StatFs fs = new StatFs(dir.getAbsolutePath());
+ availableSpace = (double) (fs.getAvailableBlocks()) * fs.getBlockSize() / (1 << 30) - clipSpace;
+ }
+
+ if (usedSpace + clipSpace > storageSize || clipSpace > availableSpace) {
+ Arrays.sort(files, new Comparator() {
+ @Override
+ public int compare(File lhs, File rhs) {
+ return lhs.lastModified() < rhs.lastModified() ? -1 : (lhs.lastModified() == rhs.lastModified() ? 0 : 1);
+ }
+ });
+ boolean wasAnyDeleted = false;
+ ArrayList arr = new ArrayList<>(Arrays.asList(files));
+ while (arr.size() > 0
+ && (usedSpace + clipSpace > storageSize || clipSpace > availableSpace)) {
+ File f = arr.remove(0);
+ double length = ((double) f.length()) / (1 << 30);
+ Recording r = recordingByFileName.get(f.getName());
+ if (r != null) {
+ deleteRecording(r, false);
+ wasAnyDeleted = true;
+ usedSpace -= length;
+ availableSpace += length;
+ } else if (f.delete()) {
+ usedSpace -= length;
+ availableSpace += length;
+ }
+ }
+ if (wasAnyDeleted) {
+ app.runInUIThread(new Runnable() {
+ @Override
+ public void run() {
+ mapActivity.refreshMap();
+ }
+ }, 20);
+ }
+ }
+ }
+ }
+
private void runMediaRecorder(final MapActivity mapActivity, MediaRecorder mr, final File f) throws IOException {
mr.prepare();
mr.start();
@@ -1375,26 +1482,42 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
recordControl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- stopRecording(mapActivity);
+ stopRecording(mapActivity, false);
}
});
}
- public void stopRecording(final MapActivity mapActivity) {
+ public void stopRecording(final MapActivity mapActivity, boolean restart) {
if (!recordingDone) {
- recordingDone = true;
- if (!recordControl.isVisible()) {
- recordControl.setExplicitlyVisible(false);
- mapActivity.getMapLayers().getMapInfoLayer().recreateControls();
+ if (!restart || !stopCameraRecording(true)) {
+ recordingDone = true;
+ if (!recordControl.isVisible()) {
+ recordControl.setExplicitlyVisible(false);
+ mapActivity.getMapLayers().getMapInfoLayer().recreateControls();
+ }
+ stopCameraRecording(false);
+ if (recordControl != null) {
+ setRecordListener(recordControl, mapActivity);
+ }
+ SHOW_RECORDINGS.set(true);
+ mapActivity.getMapView().refreshMap();
+ updateWidgetIcon(recordControl);
+ closeRecordingMenu();
}
- stopCameraRecording(mapActivity);
- SHOW_RECORDINGS.set(true);
- mapActivity.getMapView().refreshMap();
- updateWidgetIcon(recordControl);
- closeRecordingMenu();
}
}
+ private LatLon getNextRecordingLocation() {
+ double lat = mapActivity.getMapLocation().getLatitude();
+ double lon = mapActivity.getMapLocation().getLongitude();
+ Location loc = app.getLocationProvider().getLastKnownLocation();
+ if (loc != null) {
+ lat = loc.getLatitude();
+ lon = loc.getLongitude();
+ }
+ return new LatLon(lat, lon);
+ }
+
private void updateContextMenu(Recording rec) {
if (mapActivity != null && rec != null) {
MapContextMenu menu = mapActivity.getContextMenu();
@@ -1450,14 +1573,17 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
recordingByFileName = newMap;
if (isRecording()) {
+ AVActionType type = currentRecording.type;
finishRecording();
- final Recording recordingForMenu = r;
- app.runInUIThread(new Runnable() {
- @Override
- public void run() {
- updateContextMenu(recordingForMenu);
- }
- }, 200);
+ if (!AV_RECORDER_SPLIT.get() || type != AVActionType.REC_VIDEO) {
+ final Recording recordingForMenu = r;
+ app.runInUIThread(new Runnable() {
+ @Override
+ public void run() {
+ updateContextMenu(recordingForMenu);
+ }
+ }, 200);
+ }
}
return true;
@@ -1527,14 +1653,16 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
}
- public void deleteRecording(Recording r) {
+ public void deleteRecording(Recording r, boolean updateUI) {
recordings.unregisterObject(r.lat, r.lon, r);
Map newMap = new LinkedHashMap<>(recordingByFileName);
newMap.remove(r.file.getName());
recordingByFileName = newMap;
Algorithms.removeAllFiles(r.file);
- if (mapActivity != null) {
- mapActivity.getContextMenu().close();
+ if (mapActivity != null && updateUI) {
+ if (mapActivity.getContextMenu().getObject() == r) {
+ mapActivity.getContextMenu().close();
+ }
mapActivity.getMapView().refreshMap();
}
}
diff --git a/OsmAnd/src/net/osmand/plus/audionotes/NotesFragment.java b/OsmAnd/src/net/osmand/plus/audionotes/NotesFragment.java
index b9cb0c2411..1b2ad689fa 100644
--- a/OsmAnd/src/net/osmand/plus/audionotes/NotesFragment.java
+++ b/OsmAnd/src/net/osmand/plus/audionotes/NotesFragment.java
@@ -213,7 +213,7 @@ public class NotesFragment extends OsmAndListFragment {
Iterator it = selected.iterator();
while (it.hasNext()) {
Recording pnt = it.next();
- plugin.deleteRecording(pnt);
+ plugin.deleteRecording(pnt, true);
it.remove();
listAdapter.delete(pnt);
}
@@ -505,7 +505,7 @@ public class NotesFragment extends OsmAndListFragment {
builder.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- plugin.deleteRecording(recording);
+ plugin.deleteRecording(recording, true);
listAdapter.remove(recording);
}
});
diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java
index 2cbef200cf..d2d7bbca58 100644
--- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java
+++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java
@@ -327,12 +327,16 @@ public class RoutePreferencesMenu {
btn.setTextColor(btn.getLinkTextColors());
String voiceProvider = settings.VOICE_PROVIDER.get();
String voiceProviderStr;
- if (OsmandSettings.VOICE_PROVIDER_NOT_USE.equals(voiceProvider)) {
- voiceProviderStr = getString(R.string.shared_string_do_not_use);
+ if (voiceProvider != null) {
+ if (OsmandSettings.VOICE_PROVIDER_NOT_USE.equals(voiceProvider)) {
+ voiceProviderStr = getString(R.string.shared_string_do_not_use);
+ } else {
+ voiceProviderStr = FileNameTranslationHelper.getVoiceName(mapActivity, voiceProvider);
+ }
+ voiceProviderStr += voiceProvider.contains("tts") ? " TTS" : "";
} else {
- voiceProviderStr = FileNameTranslationHelper.getVoiceName(mapActivity, voiceProvider);
+ voiceProviderStr = getString(R.string.shared_string_not_selected);
}
- voiceProviderStr += voiceProvider.contains("tts") ? " TTS" : "";
btn.setText(voiceProviderStr);
btn.setOnClickListener(new View.OnClickListener() {
@Override