Commit 015288c5 authored by mistermad's avatar mistermad
Browse files

- Add the possibility of respeak or translate an elicited file

- Corrects a bug that prevents the translation or respeaking from translated or respeaked file
- Minor bug fix on user interface
parent b11287c3
package org.getalp.ligaikuma.lig_aikuma;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
/**
* Instrumentation test, which will execute on an Android device.
*
......@@ -19,8 +15,5 @@ public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("org.getalp.ligaikuma.lig_aikuma", appContext.getPackageName());
}
}
......@@ -86,7 +86,7 @@ public class ModeSelection extends Activity implements OnClickListener{
prefsUserSession = getSharedPreferences("userSession", MODE_PRIVATE);
ed = prefsUserSession.edit();
File f = new File(FileIO.getAppRootPath()+"/example");
File f = new File(FileIO.getAppRootPath()+"/examples");
if(!f.exists())
{
f.mkdir();
......
......@@ -31,6 +31,7 @@ import java.util.UUID;
import static junit.framework.Assert.assertTrue;
import static org.getalp.ligaikuma.lig_aikuma.model.RecordingLig.MAP_EXT;
import static org.getalp.ligaikuma.lig_aikuma.util.AikumaSettings.getLatestVersion;
/**
* The class that stores the metadata of a recording, including it's ID,
......@@ -167,6 +168,7 @@ public class Recording extends FileModel {
setRespeakingId("");
} else {
// Then we must generate the 4 digit respeaking ID.
Log.d(TAG, "generate : "+IdUtils.randomDigitString(6)+"|"+IdUtils.randomDigitString(6));
setRespeakingId(IdUtils.randomDigitString(6));
}
setId(determineId());
......@@ -444,6 +446,7 @@ public class Recording extends FileModel {
}
public String getRespeakingId() {
Log.d(TAG, "getRespeakingId() = "+respeakingId);
return respeakingId;
}
......@@ -643,8 +646,7 @@ public class Recording extends FileModel {
assertTrue(groupMetadataFileArray.length == 1);
return Recording.read(groupMetadataFileArray[0]);
} else {
return Recording.read(new File(FileIO.getAppRootPath(),
"/recordings/" + name + name + METADATA_SUFFIX));
return Recording.read(new File(FileIO.getAppRootPath(), "/recordings/" + name + name + METADATA_SUFFIX));
}
}
......@@ -660,8 +662,7 @@ public class Recording extends FileModel {
*/
public static Recording read(String verName, String ownerAccount,
String id) throws IOException {
File metadataFile = new File(getRecordingsPath(FileIO.getOwnerPath(verName, ownerAccount)),
getGroupIdFromId(id) + "/" + id + METADATA_SUFFIX);
File metadataFile = new File(getRecordingsPath(FileIO.getOwnerPath(verName, ownerAccount)), getGroupIdFromId(id) + "/" + id + METADATA_SUFFIX);
if(BuildConfig.DEBUG)Log.i(TAG, metadataFile.getAbsolutePath());
return read(metadataFile);
}
......@@ -687,12 +688,9 @@ public class Recording extends FileModel {
public static Recording read(JSONObject jsonObj) throws IOException {
String groupId = (String) jsonObj.get("item_id");
if (groupId == null)
throw new IOException("Null groupId in the JSON file.");
String name = (String) jsonObj.get("name"),
dateString = (String) jsonObj.get("date");
if (dateString == null)
throw new IOException("Null date in the JSON file.");
if(groupId == null) throw new IOException("Null groupId in the JSON file.");
String name = (String) jsonObj.get("name"), dateString = (String) jsonObj.get("date");
if(dateString == null) throw new IOException("Null date in the JSON file.");
Date date;
try {
date = new StandardDateFormat().parse(dateString);
......@@ -705,20 +703,19 @@ public class Recording extends FileModel {
format = (String) jsonObj.get("Format"),
fileType = (String) jsonObj.get("file_type");
JSONArray languageArray = (JSONArray) jsonObj.get("languages");
JSONArray languageArray = (JSONArray) jsonObj.get("languages");
if(languageArray == null) throw new IOException("Null languages in the JSON file.");
List<Language> languages = Language.decodeJSONArray(languageArray);
JSONArray speakerIdArray = (JSONArray) jsonObj.get("speakers");
List<Language> languages = Language.decodeJSONArray(languageArray);
JSONArray speakerIdArray = (JSONArray) jsonObj.get("speakers");
if(speakerIdArray == null) throw new IOException("Null speakersIds in the JSON file.");
List<String> speakersIds = Speaker.decodeJSONArray(speakerIdArray);
String androidID = (String) jsonObj.get("androidID");
List<String> speakersIds = Speaker.decodeJSONArray(speakerIdArray);
String androidID = (String) jsonObj.get("androidID");
if(androidID == null) throw new IOException("Null androidID in the JSON file.");
String respeakingId = (String) jsonObj.get("suffix");
String respeakingId = (String) jsonObj.get("suffix");
if(respeakingId == null) throw new IOException("Null respeakingId in the JSON file.");
long sampleRate = (jsonObj.get(RecordActivityLig.intent_sampleRate) == null)?
-1:
(Long) jsonObj.get(RecordActivityLig.intent_sampleRate);
-1: (Long) jsonObj.get(RecordActivityLig.intent_sampleRate);
return new Recording(name, date, versionName, ownerId,
sourceVerId, languages, speakersIds, androidID, groupId,
......@@ -787,8 +784,7 @@ public class Recording extends FileModel {
if (!recording.isOriginal())
respeakings.add(recording);
} catch (IOException e) {
// Well we can't read the recordings metadata file, so just
// continue on.
// Well we can't read the recordings metadata file, so just continue on.
}
}
}
......@@ -887,8 +883,8 @@ public class Recording extends FileModel {
for(File f3 : f2.listFiles())
for(File f4 : f3.listFiles()) {
if(BuildConfig.DEBUG)Log.i(TAG, "indexAll: " + f4.getPath());
for(File f5 : getRecordingsPath(f4).listFiles()) {
if (f5.isDirectory()) {
for(File f5 : getRecordingsPath(f4).listFiles())
if(f5.isDirectory()) {
// Record the path to this item folder
String itemName = f5.getName();
......@@ -913,7 +909,6 @@ public class Recording extends FileModel {
}
}
}
}
}
for(String srcId : originals)
......@@ -937,7 +932,7 @@ public class Recording extends FileModel {
switch(versionNum) {
case 0:
for(File f2 : new File(FileIO.getAppRootPath(), "v01").listFiles())
for(File f2 : new File(FileIO.getAppRootPath()+getLatestVersion()).listFiles())
for(File f3 : f2.listFiles())
for(File f : f3.listFiles()) {
if(BuildConfig.DEBUG)Log.i(TAG, "updateAll: " + f.getPath());
......@@ -946,8 +941,8 @@ public class Recording extends FileModel {
}
}
private static void updateMetadataInDir(File dir,
Map<String, Object> newJSONFields, Map<String, String> newJSONKeys) {
private static void updateMetadataInDir(File dir, Map<String, Object> newJSONFields, Map<String, String> newJSONKeys)
{
boolean isFields = (newJSONFields != null), isKeys = (newJSONKeys != null);
// Constructs a list of directories in the recordings directory.
File[] recordingPathFiles = getRecordingsPath(dir).listFiles();
......@@ -955,8 +950,8 @@ public class Recording extends FileModel {
if(recordingPathFiles == null)
return;
for (File f : recordingPathFiles) {
if (f.isDirectory()) {
for(File f : recordingPathFiles)
if(f.isDirectory())
// For each of those subdirectories, creates a list of files
// within that end in .json
// Iterate over those recording metadata files and add the
......@@ -981,8 +976,6 @@ public class Recording extends FileModel {
if(BuildConfig.DEBUG)Log.e(TAG, "Metadata update failed: " + e.toString());
}
}
}
}
}
/**
......@@ -1021,8 +1014,7 @@ public class Recording extends FileModel {
// Sets the date; the date cannot be null.
private void setDate(Date date) {
if(date == null)
throw new IllegalArgumentException("Recording date cannot be null.");
if(date == null) throw new IllegalArgumentException("Recording date cannot be null.");
this.date = date;
}
......@@ -1041,10 +1033,7 @@ public class Recording extends FileModel {
// Sets the languages
private void setLanguages(List<Language> languages) {
if (languages == null)
throw new IllegalArgumentException(
"Recording languages cannot be null. " +
"Set as an empty List<Language> instead.");
if(languages == null) throw new IllegalArgumentException("Recording languages cannot be null. Set as an empty List<Language> instead.");
this.languages = languages;
}
......@@ -1055,19 +1044,14 @@ public class Recording extends FileModel {
* languages.
*/
private void addLanguage(Language language) {
if(language == null)
throw new IllegalArgumentException(
"A language for the recording cannot be null");
if(language == null) throw new IllegalArgumentException("A language for the recording cannot be null");
this.languages.add(language);
}
// Sets the speakers Ids, but won't accept a null list (empty lists are
// fine).
private void setSpeakersIds(List<String> speakersIds) {
if(speakersIds == null)
throw new IllegalArgumentException(
"Recording speakersIds cannot be null. " +
"Set as an empty List<String> instead.");
if(speakersIds == null) throw new IllegalArgumentException("Recording speakersIds cannot be null. Set as an empty List<String> instead.");
this.speakersIds = speakersIds;
}
......@@ -1078,24 +1062,18 @@ public class Recording extends FileModel {
* speaker.
*/
private void addSpeakerId(Speaker speaker) {
if(speaker == null)
throw new IllegalArgumentException(
"A speaker for the recording cannot be null");
if(speaker == null) throw new IllegalArgumentException("A speaker for the recording cannot be null");
this.speakersIds.add(speaker.getId());
}
public void setDeviceName(String deviceName) {
if (deviceName == null)
throw new IllegalArgumentException(
"The model name cannot be null");
if(deviceName == null) throw new IllegalArgumentException("The model name cannot be null");
this.deviceName = deviceName.toUpperCase();
}
// Sets the android ID but won't accept a null string.
private void setAndroidID(String androidID) {
if (androidID == null)
throw new IllegalArgumentException(
"The androidID for the recording cannot be null");
if(androidID == null) throw new IllegalArgumentException("The androidID for the recording cannot be null");
this.androidID = androidID;
}
......@@ -1113,6 +1091,7 @@ public class Recording extends FileModel {
}
private void setRespeakingId(String respeakingId) {
Log.d(TAG, "setRespeakingId() = "+respeakingId);
this.respeakingId = respeakingId;
}
......@@ -1179,8 +1158,7 @@ public class Recording extends FileModel {
*/
public void star(String currentVerName, String userId) throws IOException {
Aikuma.getAndroidID(); //TODO: <=== Utile?
File starFile = new File(FileIO.getOwnerPath(currentVerName, userId),
"/social/" + getId() + "-like");
File starFile = new File(FileIO.getOwnerPath(currentVerName, userId), "/social/" + getId() + "-like");
starFile.getParentFile().mkdirs();
starFile.createNewFile();
}
......@@ -1195,30 +1173,10 @@ public class Recording extends FileModel {
*/
public void flag(String currentVerName, String userId) throws IOException {
Aikuma.getAndroidID(); //TODO: <=== Utile?
File flagFile = new File(FileIO.getOwnerPath(currentVerName, userId),
"/social/" + getId() + "-report");
File flagFile = new File(FileIO.getOwnerPath(currentVerName, userId), "/social/" + getId() + "-report");
flagFile.getParentFile().mkdirs();
flagFile.createNewFile();
}
/**
* Make the archived recording's metadata
* @param backupDate when upload finished
* @param downloadUrl url where the recording file can be downloaded
* @throws IOException In case of an issue writing the archiveMetadata file.
* Note that this will not be thrown if the file already exists.
*/
public void archive(String backupDate, String downloadUrl) throws IOException {
JSONObject archiveMetadata = new JSONObject();
archiveMetadata.put("name", this.name);
archiveMetadata.put("recording", this.groupId);
archiveMetadata.put("backupDate", backupDate);
archiveMetadata.put("download_url", downloadUrl);
FileIO.writeJSONObject(new File(getRecordingsPath(),
getGroupId() + "/" + id + "-archive.json"),
archiveMetadata);
}
/**
* Tells us whether this phone has already starred the Recording
......@@ -1243,15 +1201,6 @@ public class Recording extends FileModel {
public boolean isFlaggedByThisPhone(String currentVerName, String userId) {
return new File(FileIO.getOwnerPath(currentVerName, userId), "/social/" + getId() + "-report").exists();
}
/**
* Tells us whether this recording has been archived
*
* @return true if a archiveMetadata file is present; false otherwise
*/
public boolean isArchived() {
return new File(getRecordingsPath(), getGroupId() + "/" + getId() + "-archive.json").exists();
}
/**
* Gives the number of stars this recording has received.
......@@ -1261,11 +1210,8 @@ public class Recording extends FileModel {
public int numStars() {
// TODO: New file-storage model needs to be decided (1. create index / 2. put these in app-root folder)
File[] starFiles = new File(FileIO.getOwnerPath(versionName, ownerId), "/social/" + getGroupId() + "/" + getId()).listFiles(
new FilenameFilter() {
public boolean accept(File dir, String filename) {
return filename.endsWith(".star");
}
});
new FilenameFilter() {public boolean accept(File dir, String filename) {
return filename.endsWith(".star");}});
return (starFiles == null)? 0 :starFiles.length;
}
......@@ -1277,11 +1223,8 @@ public class Recording extends FileModel {
public int numFlags() {
// TODO: New file-storage model needs to be decided (1. create index / 2. put these in app-root folder)
File[] flagFiles = new File(FileIO.getOwnerPath(versionName, ownerId), "/social/" + getGroupId() + "/" + getId()).listFiles(
new FilenameFilter() {
public boolean accept(File dir, String filename) {
return filename.endsWith(".flag");
}
});
new FilenameFilter() {public boolean accept(File dir, String filename) {
return filename.endsWith(".flag");}});
return (flagFiles == null)? 0: flagFiles.length;
}
......@@ -1296,7 +1239,7 @@ public class Recording extends FileModel {
return (flagFiles == null)? 0: flagFiles.length;
}
/**
/* *
* Indicates that this recording is allowed to be synced by moving it to a
* directory that the SyncUtil synchronizes.
*
......
......@@ -2,7 +2,10 @@ package org.getalp.ligaikuma.lig_aikuma.model;
import android.util.Log;
import com.semantive.waveformandroid.waveform.MediaPlayerFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.getalp.ligaikuma.lig_aikuma.Aikuma;
import org.getalp.ligaikuma.lig_aikuma.lig_aikuma.BuildConfig;
import org.getalp.ligaikuma.lig_aikuma.ui.RecordingMetadataLig;
......@@ -33,11 +36,11 @@ public class RecordingLig extends Recording {
/**
* The constructor used when we create a translation or respeaking
* @param recordingUUID The temporary UUID of the recording in question.
* @param recordingUUID The temporary UUID of the recording in question.
* (recording can be wav or movie(mp4))
* @param name The recording's name
* @param date The date of creation
* @param versionName The recording's version (v0x)
* @param name The recording's name
* @param date The date of creation
* @param versionName The recording's version (v0x)
* @param ownerId The recording owner's ID(Google account)
* @param recordLang The recording record language
* @param motherTong The recording mother language
......@@ -45,27 +48,27 @@ public class RecordingLig extends Recording {
* @param speakersIds The Ids of the speakers associated with the recording
* @param deviceName The model name of the device
* @param androidID The android ID of the device that created the recording
* (androidId is unique for one device)
* (androidId is unique for one device)
* @param groupId The ID of the group of recordings this recording
* @param sourceVerId The version-ID of the source recording of this recording
* @param respeakingId The original name of the file (without extension)
* @param sampleRate The sample rate of the recording
* @param durationMsec The duration of the recording in milliseconds
* @param format The mime type
* @param format The mime type
* @param numChannels The number of channels of the audio
* @param bitsPerSample The bits per sample of the audio
* @param bitsPerSample The bits per sample of the audio
* @param latitude The location data
* @param longitude The location data
* @param region The region where the recording has been done
* @param region The region where the recording has been done
* @param spkrName The name of the speaker who did the recording
* @param spkrAge The age of the speaker who did the recording
* @param spkrAge The age of the speaker who did the recording
* @param spkrGndr The gender of the speaker who did the recording
* @param spkrNote Optionnal additionnal note
*/
public RecordingLig(UUID recordingUUID, String name, Date date,
String versionName, String ownerId, Language recordLang, Language motherTong,
List<Language> languages, List<String> speakersIds,
String deviceName, String androidID, String groupId, String sourceVerId, String respeakingId,
List<Language> languages, List<String> speakersIds, String deviceName,
String androidID, String groupId, String sourceVerId, String respeakingId,
long sampleRate, int durationMsec, String format, int numChannels,
int bitsPerSample, Double latitude, Double longitude,
String region, String spkrName, int spkrAge, String spkrGndr, String spkrNote) {
......@@ -95,6 +98,7 @@ public class RecordingLig extends Recording {
languages, speakersIds, deviceName, androidID, groupId,
sourceVerId, sampleRate, durationMsec, format, numChannels,
bitsPerSample, latitude, longitude);
Log.d(TAG, "sourceVerId(2) (respeakingId) = "+sourceVerId);
this.regionOrigin = region;
this.speakerName = spkrName;
this.speakerBirthYear = spkrAge;
......@@ -106,7 +110,6 @@ public class RecordingLig extends Recording {
: new Language("", "");
}
// Never use
public RecordingLig(UUID recordingUUID, String name, Date date,
String versionName, String ownerId,
List<Language> languages, List<String> speakersIds,
......@@ -131,7 +134,6 @@ public class RecordingLig extends Recording {
* Public constructor from super class Recording
* for existing recordings
* @param r the original recording
* @return an instance of RecordingLig
*/
public RecordingLig(Recording r) {
super(r.name, r.date, r.versionName, r.ownerId, r.sourceVerId,
......@@ -181,14 +183,12 @@ public class RecordingLig extends Recording {
dir.mkdir();
if(BuildConfig.DEBUG)Log.i(TAG, "start write - iniate directory " + dir.getAbsolutePath());
// Import the wave file into the new recording directory.
Log.d(TAG, "A1");
if(this.isMovie())
// TODO update importMov
super.importMov(recordingUUID, getId());
else
this.importWav(recordingUUID, WAV_EXT);
Log.d(TAG, "A2");
// if the recording is original
if(isOriginal() || isElicit()) {
// Import the sample wave file into the new recording directory
......@@ -204,15 +204,49 @@ public class RecordingLig extends Recording {
}
JSONObject encodedRecording = this.encode();
Log.d(TAG, "A3");
// Write the json metadata.
File metadataFile = new File(dir.toString(), this.name + METADATA_SUFFIX);
FileIO.writeJSONObject(metadataFile,encodedRecording);
Log.i(TAG, "Saved metadata file to " + metadataFile.getAbsolutePath());
Log.d(TAG, "A4");
// To respeaking elicitation file, move it at right location
moveRespeakedElicitationFile();
}
/**
* Move all files at right location when respek an elicitation file.
* Edit matadate file with right data
*/
public void moveRespeakedElicitationFile() {
if(MediaPlayerFactory._elicit_source.isEmpty()||MediaPlayerFactory._elicit_rspk.isEmpty()) return;
String source = FileIO.getOwnerPath()+"/recordings/"+ MediaPlayerFactory._elicit_rspk+"/",
dest = "/"+FilenameUtils.getPath(MediaPlayerFactory._elicit_source),
num = new File(MediaPlayerFactory._elicit_source).getName().split("_")[4].replace(".wav","");
File f = new File(source);
try {
for(String s : f.list()) {
if(s.contains(METADATA_SUFFIX)&&(s.contains("_rspk")||s.contains("_trsl")))
{
File tf = new File(source+s);
String t = FileIO.read(tf);
FileIO.delete(tf);
FileIO.write(tf,t.replaceFirst(MediaPlayerFactory._elicit_rspk,FilenameUtils.getBaseName(MediaPlayerFactory._elicit_source)));
}
if(s.contains("_rspk"))
FileUtils.moveFile(new File(source+s), new File(dest+s.replace("_rspk", "_elicit_" + num + "_rspk")));
else if(s.contains("_trsl"))
FileUtils.moveFile(new File(source + s), new File(dest + s.replace("_trsl", "_elicit_" + num + "_trsl")));
}
// Delete "temporary" files and directory
FileUtils.deleteDirectory(f);
// Clear memory of path
MediaPlayerFactory._elicit_source = "";
MediaPlayerFactory._elicit_rspk = "";
} catch (IOException ignored) {}
}
/**
......@@ -251,7 +285,6 @@ public class RecordingLig extends Recording {
*/
public JSONObject encode() {
JSONObject encodedRecording = super.encode();
// TODO complete with new metadata
encodedRecording.put(RecordingMetadataLig.metaOrigin, regionOrigin);
encodedRecording.put(RecordingMetadataLig.metaSpkrName, speakerName);
encodedRecording.put(RecordingMetadataLig.metaSpkrNote, speakerNote);
......@@ -280,7 +313,7 @@ public class RecordingLig extends Recording {
* @return True if the recording is an elicitation.
*/
public boolean isElicit() {
return this.name.contains("_elicit_") && !this.name.contains("_rspk") && !this.name.contains("_trsl");
return this.name.contains("_elicit_") && !(this.name.contains("_rspk") || this.name.contains("_trsl"));
}
......@@ -297,28 +330,25 @@ public class RecordingLig extends Recording {
*/
public File getIndividualRecordingPath() {
File path = null;
Log.d(TAG, "getIndividualRecordingPath() base path: "+this.getRespeakingId());
String[] dir = this.getRespeakingId().split("_");
if (this.name.contains("rspk") || this.name.contains("trsl")) {
if (dir.length < 4) {
if(dir.length < 4) {
if(BuildConfig.DEBUG)Log.d(TAG, "path -> "+this.getRespeakingId());
path = new File(getRecordingsPath(),
dir[0] + "_" + dir[1] + "_" + dir[2] + "/");
} else {
if (dir[3].equals("elicit")) {
if(BuildConfig.DEBUG)Log.d(TAG, "elicitation path -> "+this.getRespeakingId());
path = new File(getRecordingsPath(),
dir[0] + "_" + dir[1] + "_" + dir[2] + "_" + dir[3] + "/");
}
path = new File(getRecordingsPath(), dir[0] + "_" + dir[1] + "_" + dir[2] + "/");
} else if(dir[3].equals("elicit")) {
if(BuildConfig.DEBUG)Log.d(TAG, "elicitation path -> "+this.getRespeakingId());
path = new File(getRecordingsPath(), dir[0] + "_" + dir[1] + "_" + dir[2] + "_" + dir[3] + "/");
}
} else if (isElicit()) {
if(BuildConfig.DEBUG)Log.d(TAG, "elicitation path -> "+this.getRespeakingId());
path = new File(getRecordingsPath(),
dir[0] + "_" + dir[1] + "_" + dir[2] + "_" + dir[3] + "/");
} else
path = new File(getRecordingsPath(), dir[0] + "_" + dir[1] + "_" + dir[2] + "_" + dir[3] + "/");
} else {
if(BuildConfig.DEBUG)Log.d(TAG, "other -> "+this.name);
path = new File(getRecordingsPath(), this.name + "/");
}
path.mkdirs();
if(BuildConfig.DEBUG)Log.d(TAG, "destPath: "+path.toString());
return path;
}
}
......@@ -56,14 +56,6 @@ public class AboutActivity extends AikumaActivity {