mirror of
https://github.com/dgis/emu48android
synced 2024-12-26 09:58:49 +01:00
- Fix an issue when the permission to read the KML folder has been lost.
- Remove unused win32 timer source code.
This commit is contained in:
parent
efc2139026
commit
100e6ef24e
7 changed files with 36 additions and 142 deletions
|
@ -63,9 +63,10 @@ LINKS
|
|||
|
||||
CHANGES
|
||||
|
||||
Version 2.2 (2020-12-08)
|
||||
Version 2.2 (2020-12-09)
|
||||
|
||||
- The KML folder is now saved when changing the KML script for a custom one via the menu "Change KML Script...".
|
||||
- The KML folder is now well saved when changing the KML script for a custom one via the menu "Change KML Script...".
|
||||
- Fix an issue when the permission to read the KML folder has been lost.
|
||||
|
||||
|
||||
Version 2.1 (2020-11-23)
|
||||
|
|
|
@ -19,7 +19,6 @@ cmake_minimum_required(VERSION 3.4.1)
|
|||
#add_compile_options(-DDEBUG_ANDROID_FILE)
|
||||
|
||||
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE)
|
||||
#add_compile_options(-DWIN32_TIMER_THREAD) # old timer algorithm which stop when no more thread!
|
||||
|
||||
add_compile_options(-DEMUXX=48)
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ android {
|
|||
applicationId "org.emulator.forty.eight"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 29
|
||||
versionCode 18
|
||||
versionName "2.1"
|
||||
versionCode 20
|
||||
versionName "2.2"
|
||||
setProperty("archivesBaseName", "Emu48-v$versionName")
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
|
|
|
@ -63,9 +63,10 @@ LINKS
|
|||
|
||||
CHANGES
|
||||
|
||||
Version 2.2 (2020-12-08)
|
||||
Version 2.2 (2020-12-09)
|
||||
|
||||
- The KML folder is now saved when changing the KML script for a custom one via the menu "Change KML Script...".
|
||||
- The KML folder is now well saved when changing the KML script for a custom one via the menu "Change KML Script...".
|
||||
- Fix an issue when the permission to read the KML folder has been lost.
|
||||
|
||||
|
||||
Version 2.1 (2020-11-23)
|
||||
|
|
|
@ -2498,128 +2498,6 @@ HANDLE WINAPI GetClipboardData(UINT uFormat) {
|
|||
return szText;
|
||||
}
|
||||
|
||||
#if defined WIN32_TIMER_THREAD
|
||||
struct timerEvent {
|
||||
BOOL valid;
|
||||
int timerId;
|
||||
LPTIMECALLBACK fptc;
|
||||
DWORD_PTR dwUser;
|
||||
UINT fuEvent;
|
||||
timer_t timer;
|
||||
};
|
||||
|
||||
#define MAX_TIMER 10
|
||||
struct timerEvent timerEvents[MAX_TIMER];
|
||||
pthread_mutex_t timerEventsLock;
|
||||
static void initTimer() {
|
||||
for (int i = 0; i < MAX_TIMER; ++i) {
|
||||
timerEvents[i].valid = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void deleteTimeEvent(UINT uTimerID) {
|
||||
pthread_mutex_lock(&timerEventsLock);
|
||||
timer_delete(timerEvents[uTimerID - 1].timer);
|
||||
timerEvents[uTimerID - 1].valid = FALSE;
|
||||
pthread_mutex_unlock(&timerEventsLock);
|
||||
}
|
||||
|
||||
MMRESULT timeKillEvent(UINT uTimerID) {
|
||||
TIMER_LOGD("timeKillEvent(uTimerID: [%d])", uTimerID);
|
||||
deleteTimeEvent(uTimerID);
|
||||
return 0; //No error
|
||||
}
|
||||
|
||||
void timerCallback(int timerId) {
|
||||
if(timerId >= 0 && timerId < MAX_TIMER && timerEvents[timerId].valid) {
|
||||
timerEvents[timerId].fptc((UINT) (timerId + 1), 0, (DWORD) timerEvents[timerId].dwUser, 0, 0);
|
||||
|
||||
if(timerEvents[timerId].fuEvent == TIME_ONESHOT) {
|
||||
TIMER_LOGD("timerCallback remove timer uTimerID [%d]", timerId + 1);
|
||||
deleteTimeEvent((UINT) (timerId + 1));
|
||||
}
|
||||
|
||||
jniDetachCurrentThread();
|
||||
}
|
||||
}
|
||||
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) {
|
||||
TIMER_LOGD("timeSetEvent(uDelay: %d, fuEvent: %d)", uDelay, fuEvent);
|
||||
|
||||
pthread_mutex_lock(&timerEventsLock);
|
||||
|
||||
// Find a timer id
|
||||
int timerId = -1;
|
||||
for (int i = 0; i < MAX_TIMER; ++i) {
|
||||
if(!timerEvents[i].valid) {
|
||||
timerId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(timerId == -1) {
|
||||
LOGD("timeSetEvent() ERROR: No more timer available");
|
||||
pthread_mutex_unlock(&timerEventsLock);
|
||||
return NULL;
|
||||
}
|
||||
timerEvents[timerId].timerId = timerId;
|
||||
timerEvents[timerId].fptc = fptc;
|
||||
timerEvents[timerId].dwUser = dwUser;
|
||||
timerEvents[timerId].fuEvent = fuEvent;
|
||||
|
||||
|
||||
struct sigevent sev;
|
||||
sev.sigev_notify = SIGEV_THREAD;
|
||||
sev.sigev_notify_function = (void (*)(sigval_t)) timerCallback; //this function will be called when timer expires
|
||||
sev.sigev_value.sival_int = timerEvents[timerId].timerId; //this argument will be passed to cbf
|
||||
sev.sigev_notify_attributes = NULL;
|
||||
timer_t * timer = &(timerEvents[timerId].timer);
|
||||
|
||||
// CLOCK_REALTIME 0 OK but X intervals only
|
||||
// CLOCK_MONOTONIC 1 OK but X intervals only
|
||||
// CLOCK_PROCESS_CPUTIME_ID 2 NOTOK, not working with PERIODIC!
|
||||
// CLOCK_THREAD_CPUTIME_ID 3 NOTOK
|
||||
// CLOCK_MONOTONIC_RAW 4 NOTOK
|
||||
// CLOCK_REALTIME_COARSE 5 NOTOK
|
||||
// CLOCK_MONOTONIC_COARSE 6 NOTOK
|
||||
// CLOCK_BOOTTIME 7 OK but X intervals only
|
||||
// CLOCK_REALTIME_ALARM 8 NOTOK EPERM
|
||||
// CLOCK_BOOTTIME_ALARM 9 NOTOK EPERM
|
||||
// CLOCK_SGI_CYCLE 10 NOTOK EINVAL
|
||||
// CLOCK_TAI 11
|
||||
|
||||
if (timer_create(CLOCK_REALTIME, &sev, timer) == -1) {
|
||||
LOGD("timeSetEvent() ERROR in timer_create, errno: %d (EAGAIN 11 / EINVAL 22 / ENOMEM 12)", errno);
|
||||
// EAGAIN Temporary error during kernel allocation of timer structures.
|
||||
// EINVAL Clock ID, sigev_notify, sigev_signo, or sigev_notify_thread_id is invalid.
|
||||
// ENOMEM Could not allocate memory.
|
||||
pthread_mutex_unlock(&timerEventsLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long freq_nanosecs = uDelay;
|
||||
struct itimerspec its;
|
||||
its.it_value.tv_sec = freq_nanosecs / 1000;
|
||||
its.it_value.tv_nsec = (freq_nanosecs % 1000) * 1000000;
|
||||
if(fuEvent == TIME_PERIODIC) {
|
||||
its.it_interval.tv_sec = its.it_value.tv_sec;
|
||||
its.it_interval.tv_nsec = its.it_value.tv_nsec;
|
||||
} else /*if(fuEvent == TIME_ONESHOT)*/ {
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
}
|
||||
if (timer_settime(timerEvents[timerId].timer, 0, &its, NULL) == -1) {
|
||||
LOGD("timeSetEvent() ERROR in timer_settime, errno: %d (EFAULT 14 / EINVAL 22)", errno);
|
||||
// EFAULT new_value, old_value, or curr_value is not a valid pointer.
|
||||
// EINVAL timerid is invalid. Or new_value.it_value is negative; or new_value.it_value.tv_nsec is negative or greater than 999,999,999.
|
||||
timer_delete(timerEvents[timerId].timer);
|
||||
pthread_mutex_unlock(&timerEventsLock);
|
||||
return NULL;
|
||||
}
|
||||
timerEvents[timerId].valid = TRUE;
|
||||
TIMER_LOGD("timeSetEvent() -> timerId+1: [%d]", timerId + 1);
|
||||
pthread_mutex_unlock(&timerEventsLock);
|
||||
return (MMRESULT) (timerId + 1); // No error
|
||||
}
|
||||
#else
|
||||
struct timerEvent {
|
||||
int timerId;
|
||||
UINT uDelay;
|
||||
|
@ -2707,7 +2585,7 @@ static void insertTimer(struct timerEvent * newTimer) {
|
|||
}
|
||||
|
||||
static void timerThreadStart(LPVOID lpThreadParameter) {
|
||||
LOGD("timerThreadStart() START");
|
||||
TIMER_LOGD("timerThreadStart() START");
|
||||
pthread_mutex_lock(&timerEventsLock);
|
||||
while (!timerThreadToEnd) {
|
||||
TIMER_LOGD("timerThreadStart() %ld", GetTickCount64());
|
||||
|
@ -2768,7 +2646,7 @@ static void timerThreadStart(LPVOID lpThreadParameter) {
|
|||
timerThreadId = 0;
|
||||
pthread_mutex_unlock(&timerEventsLock);
|
||||
jniDetachCurrentThread();
|
||||
LOGD("timerThreadStart() END");
|
||||
TIMER_LOGD("timerThreadStart() END");
|
||||
}
|
||||
|
||||
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) {
|
||||
|
@ -2793,9 +2671,9 @@ MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_
|
|||
|
||||
if(!timerThreadId) {
|
||||
// If not yet created, create the thread which will handle all the timers
|
||||
LOGD("timeSetEvent() pthread_create");
|
||||
TIMER_LOGD("timeSetEvent() pthread_create");
|
||||
if (pthread_create(&timerThreadId, NULL, (void *(*)(void *)) timerThreadStart, NULL) != 0) {
|
||||
LOGD("timeSetEvent() ERROR in pthread_create, errno: %d (EAGAIN 11 / EINVAL 22 / EPERM 1)", errno);
|
||||
TIMER_LOGD("timeSetEvent() ERROR in pthread_create, errno: %d (EAGAIN 11 / EINVAL 22 / EPERM 1)", errno);
|
||||
// EAGAIN Insufficient resources to create another thread.
|
||||
// EINVAL Invalid settings in attr.
|
||||
// ENOMEM No permission to set the scheduling policy and parameters specified in attr.
|
||||
|
@ -2808,7 +2686,6 @@ MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_
|
|||
pthread_mutex_unlock(&timerEventsLock);
|
||||
return (MMRESULT) newTimer->timerId; // No error
|
||||
}
|
||||
#endif
|
||||
|
||||
MMRESULT timeGetDevCaps(LPTIMECAPS ptc, UINT cbtc) {
|
||||
if(ptc) {
|
||||
|
|
|
@ -994,7 +994,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
// We only change the KML script here.
|
||||
int result = NativeLib.onViewScript(scriptItem.filename, scriptItem.folder);
|
||||
if(result > 0) {
|
||||
//TODO no need to call changeKMLFolder(scriptItem.folder);
|
||||
settings.putString("settings_kml_folder_embedded", scriptItem.folder);
|
||||
displayKMLTitle();
|
||||
showKMLLog();
|
||||
|
@ -1515,8 +1514,20 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
// Change the default KMLFolder to allow getFirstKMLFilenameForType() to find in the specific folder!
|
||||
Uri kmlFolderUri = Uri.parse(kmlScriptFolder);
|
||||
DocumentFile kmlFolderDocumentFile = DocumentFile.fromTreeUri(this, kmlFolderUri);
|
||||
if(kmlFolderDocumentFile != null && kmlFolderDocumentFile.exists())
|
||||
changeKMLFolder(kmlScriptFolder);
|
||||
if(kmlFolderDocumentFile != null) {
|
||||
// Check the permission of the folder kmlScriptFolder
|
||||
if (!kmlFolderDocumentFile.canRead()) {
|
||||
// Permission denied, switch to the default asset folder
|
||||
changeKMLFolder(null);
|
||||
kmlScriptFolder = null;
|
||||
showAlert(getString(R.string.message_open_kml_folder_permission_lost), true);
|
||||
} else if (kmlFolderDocumentFile.exists())
|
||||
changeKMLFolder(kmlScriptFolder);
|
||||
} else {
|
||||
// We are using the API < 21, so we
|
||||
changeKMLFolder(null);
|
||||
kmlScriptFolder = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(settings.getBoolean("settings_port2en", false)) {
|
||||
|
@ -1527,13 +1538,14 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
DocumentFile port2DocumentFile = DocumentFile.fromSingleUri(this, port2Uri);
|
||||
if (port2DocumentFile == null || !port2DocumentFile.exists()) {
|
||||
String port2Filename = getFilenameFromURL(port2Url);
|
||||
String finalKmlScriptFolder = kmlScriptFolder;
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.message_open_port2_file_not_found))
|
||||
.setMessage(String.format(Locale.US, getString(R.string.message_open_port2_file_not_found_description), port2Filename))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
|
||||
urlToOpenInIntentPort2Load = url;
|
||||
kmlScriptFolderInIntentPort2Load = kmlScriptFolder;
|
||||
kmlScriptFolderInIntentPort2Load = finalKmlScriptFolder;
|
||||
|
||||
Intent intentPort2 = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intentPort2.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
|
@ -1544,7 +1556,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
}).setNegativeButton(android.R.string.cancel, (dialog, which) -> {
|
||||
// Deactivate the port2 because it is not reachable.
|
||||
settings.putBoolean("settings_port2en", false);
|
||||
onFileOpenNative(url, kmlScriptFolder);
|
||||
onFileOpenNative(url, finalKmlScriptFolder);
|
||||
}).show();
|
||||
return;
|
||||
}
|
||||
|
@ -1936,7 +1948,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
for (int i = 0; i < kmlScripts.size(); i++) {
|
||||
KMLScriptItem kmlScriptItem = kmlScripts.get(i);
|
||||
if (kmlScriptItem.model.charAt(0) == chipsetType) {
|
||||
showAlert(String.format(Locale.US, "Existing KML script not found. Trying the compatible script: %s", kmlScriptItem.filename), true);
|
||||
showAlert(String.format(Locale.US, getString(R.string.message_open_kml_not_found_alert_trying_other1), kmlScriptItem.filename), true);
|
||||
NativeLib.setCurrentKml(kmlScriptItem.filename);
|
||||
NativeLib.setEmuDirectory(kmlFolderURL);
|
||||
return 1;
|
||||
|
@ -1953,13 +1965,13 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
for (int i = 0; i < kmlScripts.size(); i++) {
|
||||
KMLScriptItem kmlScriptItem = kmlScripts.get(i);
|
||||
if (kmlScriptItem.model.charAt(0) == chipsetType) {
|
||||
showAlert(String.format(Locale.US, "Existing KML script not found. Trying the embedded and compatible script: %s", kmlScriptItem.filename), true);
|
||||
showAlert(String.format(Locale.US, getString(R.string.message_open_kml_not_found_alert_trying_other2), kmlScriptItem.filename), true);
|
||||
NativeLib.setCurrentKml(kmlScriptItem.filename);
|
||||
NativeLib.setEmuDirectory("assets/calculators/");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
showAlert("Cannot find the KML template file, sorry.", true);
|
||||
showAlert(getString(R.string.message_open_kml_not_found_alert), true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,10 +93,14 @@
|
|||
<string name="message_open_security_description">For security reason, you must select the folder where are the KML and ROM files, please.</string>
|
||||
<string name="message_open_security_retry">Please, open again</string>
|
||||
<string name="message_open_security_retry_description">I hope now you could open again the state file.</string>
|
||||
<string name="message_open_kml_folder_permission_lost">Permission denied to access to the previously saved KML folder. Switch to the default embedded KML folder.</string>
|
||||
<string name="message_open_kml_not_found">KML Script not Found</string>
|
||||
<string name="message_open_kml_not_found_description">You must select the folder where are the KML and ROM files, please.</string>
|
||||
<string name="message_open_kml_not_found_description2">The KML script "%s" cannot be found. You must select the folder where are the KML and ROM files, please.</string>
|
||||
<string name="message_open_kml_not_found_description3">The KML script "%s" cannot be found in the folder "%s". You must select the folder where are the KML and ROM files, please.</string>
|
||||
<string name="message_open_kml_not_found_alert_trying_other1">Existing KML script not found. Trying the compatible script: %s</string>
|
||||
<string name="message_open_kml_not_found_alert_trying_other2">"Existing KML script not found. Trying the embedded and compatible script: %s"</string>
|
||||
<string name="message_open_kml_not_found_alert">"Cannot find the KML template file, sorry."</string>
|
||||
<string name="message_open_port2_file_not_found">Port 2 File not Found</string>
|
||||
<string name="message_open_port2_file_not_found_description">The port 2 file "%s" cannot be found. You should select it again, please.</string>
|
||||
<string name="message_state_saved">State saved in %s</string>
|
||||
|
|
Loading…
Reference in a new issue