diff --git a/doc/Changelog.html b/doc/Changelog.html
index 66cb1bc0..99c10062 100644
--- a/doc/Changelog.html
+++ b/doc/Changelog.html
@@ -26,7 +26,9 @@ a:visited { color: #0000EE; }
Implemented coalescing of update signals to reduce the CPU usage of the LameXP process (details)
Run more than four instances in parallel on systems with more than four CPU cores (details)
Improved handling of different character encodings for Playlist and Cue Sheet import
+Improved LameXP inter-process communication by adding queue support
Workaround for a bug that causes MediaInfo to not detect the duration of Wave files (64-Bit only)
+Prevent LameXP from blocking a system shutdown (encoding process is aborted, if necessary)
Changes between v4.02 and v4.03:
diff --git a/etc/Translation/Blank.ts b/etc/Translation/Blank.ts
index 3bd009da..266dcb0e 100644
--- a/etc/Translation/Blank.ts
+++ b/etc/Translation/Blank.ts
@@ -1412,9 +1412,9 @@
-
-
+
+
@@ -1455,13 +1455,13 @@
-
+
-
+
@@ -1547,7 +1547,7 @@
-
+
@@ -1647,604 +1647,604 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2714,121 +2714,121 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
@@ -2849,22 +2849,22 @@
QApplication
-
+
-
+
-
+
-
+
diff --git a/etc/Translation/LameXP_PL.ts b/etc/Translation/LameXP_PL.ts
index 5914c81a..73a7cc8c 100644
--- a/etc/Translation/LameXP_PL.ts
+++ b/etc/Translation/LameXP_PL.ts
@@ -1412,9 +1412,9 @@
-
-
+
+
Sprawdź aktualizacje
@@ -1455,13 +1455,13 @@
-
+
Wyłącz przypominanie o aktualizacji
-
+
Wyłącz efekty dźwiękowe
@@ -1547,7 +1547,7 @@
-
+
Dostęp zablokowany
@@ -1642,193 +1642,193 @@
Zapamiętaj wybrany folder
-
+
Licencja odrzucona
-
+
Odrzuciłeś licencję. W takim razie program zostanie teraz zamknięty!
-
+
Naraska!
-
+
LameXP - Termin wygasł
-
+
Ta wersja demo (beta) LameXP wygasła %1.
-
+
LameXP jest darmowym oprogramowaniem i pełna wersja nie wygasa.
-
-
+
+
Wyjdź z programu
-
+
Najwyraźniej twoje oprogramowanie antywirusowe spowalnia uruchamianie się LameXP.
-
+
Prosze sprawdzić dokument %1 w celu dalszych szcegółów i rozwiązań!
-
+
Powolny start
-
-
-
-
-
-
+
+
+
+
+
+
Zamknij
-
-
+
+
Nie pokazuj ponownie
-
+
Ważna aktualizacja
-
+
Twoja wersja LameXP jest starsza niż rok! Czas na aktualizację!
-
-
-
+
+
+
Powiadomienie aktualizacji
-
+
Ostatnie sprawdzenie aktualizacji było ponad 14 dni temu. Sprawdzić teraz aktualizacje?
-
+
Nie sprawdzałeś jeszcze aktualizacji LameXP. Sprawdzić teraz aktualizacje?
-
+
Przełóż
-
+
LameXP wykrył że Twoja wersja kodera Nero AAC jest nieaktualna!
-
+
Wersją dostępną obecnie jest %1, Twoja wersja to %2.
-
+
n/d
-
+
Możesz pobrać najnowszą wersję kodera Nero AAC ze strony Nero:
-
+
Koder AAC jest nieaktualny
-
+
Nie można odnaleźć kodera Nero AAC. Kompresja formatu AAC zostanie wyłączona.
-
+
Prosze skopiować 'neroAacEnc.exe', 'neroAacDec.exe', oraz 'neroAacTag.exe' do folderu LameXP!
-
+
Folder aplikacji LameXP znajduje się tutaj:
-
+
Możesz pobrać koder Nero AAC za darmo z oficjalnej strony Nero:
-
+
Wsparcie dla AAC wyłączone
-
-
-
+
+
+
LameXP
-
+
Powinienieś dodać przynajmniej jeden plik do listy aby zacząć działać!
-
+
Nie znaleziono
-
+
Wybrany przez Ciebie folder tymczasowy TEMP już nie istnieje:
-
+
Przywróć domyślne
-
+
Anuluj
-
+
Ostrzeżenie o małej ilości miejsca na dysku
-
+
Jest mniej niż %1 GB dostępnego miejsca w systemowym folderze TEMP.
@@ -1838,413 +1838,413 @@
WERSJA DEMO
-
+
(Podpowiedź: Zignoruj nazwę pobranego pliku ZIP, w zamian sprawdż załączony w archiwum plik "changelog.txt"!)
-
+
Jest wysoce zalecane zwolnić miejsce na dysku zanim zaczniesz kompresję!
-
+
Twój folder TEMP znajduję się:
-
+
Przerwij proces kompresji
-
+
Wykonaj oczyszczanie dysku
-
-
+
+
Ignoruj
-
+
Pomijanie sprawdzania aktualizacji, prosze czekać...
-
+
Mało miejsca na dysku
-
+
Chcesz zacząć działać z małą ilością miejsca na dysku. Mogą wystąpić problemy!
-
+
Został wybrany koder, który nie jest wspierany!
-
+
Nie można zapisać do wybranej lokalizacji.
-
+
Prosze wybrać inną lokalizację!
-
+
Zaladuj plik językowy
-
+
Pliki językowe
-
+
Czy na pewno chcesz wyłączyć przypominanie o aktualizacjach?
-
-
-
-
-
-
-
+
+
+
+
+
+
+
Tak
-
-
-
-
-
-
-
+
+
+
+
+
+
+
Nie
-
+
Przypominanie o aktualizacjach wyłączone.
-
+
Prosze pamiętać o okresowym sprawdzaniu aktualizacji!
-
+
Przypominanie o aktualizacjach ponownie włączone.
-
+
Czy na pewno chcesz wyłączyć wszystkie dźwiękowe?
-
-
+
+
Efekty dźwiękowe
-
+
Wszystkie efekty dźwiękowe zostały wyłączone.
-
+
Efekty dźwiękowe zostały ponownie włączone.
-
-
-
+
+
+
Powiadomienia Nero AAC
-
+
Czy na pewno chcesz wyłączyć wszystkie powiadomienia Nero AAC?
-
+
Wszystkie powiadomienia kodera Nero AAC zostały wyłączone.
-
+
Powiadomienia Nero AAC zostały ponownie włączone.
-
-
-
+
+
+
Powiadomienia o powolnym starcie
-
+
Czy na pewno chcesz wyłączyć powiadomienia o powolnym starcie?
-
+
Powiadomienia o powolnym starcie zostały wyłączone.
-
+
Powiadomienia o powolnym starcie zostały ponownie włączone.
-
-
+
+
Otwórz plik Cue Sheet
-
-
+
+
Plik Cue Sheet
-
-
-
+
+
+
Aktualizacje Beta
-
+
Czy na pewno chcesz aby LameXP sprawdzał aktualizacje Beta?
-
+
Od teraz LameXP będzie sprawdzał aktualizacje Beta.
-
+
Sprawdź teraz
-
+
LameXP od teraz <i>nie będzie</i> sprawdzał aktualizacji Beta.
-
-
-
+
+
+
Hibernuj komputer
-
+
Czy na pewno chcesz aby komputer był hibernowany zamiast zamykany?
-
+
Od teraz LameXP będzie hibernował komputer zamiast zamykać.
-
+
LameXP od teraz <i>nie</i> będzie hibernował komputera tylko zamykał.
-
-
-
+
+
+
Integracja z systemem
-
+
Czy na pewno chcesz wyłączyć integrację LameXP z systemem?
-
+
Integracja LameXP z systemem zostałą wyłączona.
-
+
Integracja LameXP z systemem została ponownie włączona.
-
-
+
+
Dodaj plik(i)
-
-
+
+
Dodaj folder
-
-
+
+
Nowy folder
-
+
Wprowadź nazwę nowego folderu:
-
+
Utworzenie folderu zakończone niepowodzeniem
-
+
Nowy folder nie mógł zostać stworzony:
-
+
Dysk tylko do odczytu lub brak praw dostępu!
-
-
-
-
+
+
+
+
Poziom jakości %1
-
-
-
+
+
+
Kompresja %1
-
-
-
+
+
+
Nieskompresowany
-
+
Najlepsza jakość (Bardzo wolno)
-
+
Wysoka jakość (Zalecane)
-
+
Średnia jakość (Domyślnie)
-
+
Niska jakość (Szybko)
-
+
Najniższa jakość (Bardzo szybko)
-
+
Nazwa pliku bez rozszerzenia
-
+
Numer ścieżki z zerem na początku
-
+
Nazwa ścieżki
-
+
Nazwa Artysty
-
+
Nazwa Albumu
-
+
Rok z (przynajmniej) czterema cyframi
-
+
Komentarz
-
+
Zabronione znaki w nazwach plików:
-
+
Zmień nazwy makr
-
+
%1 wątek/ki
-
+
Nie można zapisać do wybranej lokalizacji. Prosze wybierz inną lokalizację!
-
+
Już działa
-
+
LameXP już działa, przejdź do działającego programu!
@@ -2714,121 +2714,121 @@
Twoje pliki są właśnie kompresowane, prosze być cierpliwy...
-
+
Kompresowanie plików, prosze czekać...
-
+
Wielowątkowosć włączona: Równolegle wykonywanych jest %1 kodowań!
-
+
Przerwano! Czekanie na wyłączenie procesu...
-
+
Kompresja: Prosze czekać, jak dotąd wykonano %1 z %2 plików...
-
+
Tworzenie pliku playlisty, prosze czekać...
-
+
Proces został przerwany przez użytkownika po wykonaniu %1 plików!
-
+
Proces został przedwcześnie zakończony przez użytkownika!
-
+
LameXP - Przerwano
-
+
Proces został przerwany przez użytkownika.
-
+
Proces został zakończony po %1.
-
+
Błąd: %1 z %2 plików nie zostało skompresowanych. Kliknij dwukrotnie na plik aby zobaczyć szczegóły!
-
+
LameXP - Błąd
-
+
Przynajmniej jeden plik nie został skompresowany!
-
-
+
+
Kompresja wszystkich plików zakończona powodzeniem.
-
+
LameXP - Zrobione
-
+
Tworzenie playlisty zakończone niepowodzeniem
-
+
Playlista nie mogła zostać utworzona:
-
+
Ostrzeżenie: Komputer zostanie zamknięty za %1 sekund/y...
-
-
+
+
Anuluj wyłączenie komputera
-
+
godzin/y
-
-
+
+
minut/a
-
-
+
+
sekund/a
-
+
milisekund/y
@@ -2849,22 +2849,22 @@
QApplication
-
+
Plik wykonywalny '%1' nie działa w trybie kompatybilności z Windows.
-
+
Plik wykonywalny '%1' wymaga Qt v%2, znaleziono jednak Qt v%3.
-
+
Plik wykonywalny "%1" został skompilowany dla Qt "%2", znaleziono "%3".
-
+
Plik wykonywalny '%1' wymaga do uruchomienia Windows 2000 lub nowszego.
diff --git a/src/Config.h b/src/Config.h
index ddcfb7ac..04afdc62 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -29,8 +29,8 @@
#define VER_LAMEXP_MINOR_HI 0
#define VER_LAMEXP_MINOR_LO 4
#define VER_LAMEXP_TYPE Alpha
-#define VER_LAMEXP_PATCH 12
-#define VER_LAMEXP_BUILD 854
+#define VER_LAMEXP_PATCH 13
+#define VER_LAMEXP_BUILD 860
///////////////////////////////////////////////////////////////////////////////
// Tool versions (minimum expected versions!)
diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp
index 0924720a..89d93e28 100644
--- a/src/Dialog_MainWindow.cpp
+++ b/src/Dialog_MainWindow.cpp
@@ -446,7 +446,7 @@ MainWindow::~MainWindow(void)
if(m_messageHandler && m_messageHandler->isRunning())
{
m_messageHandler->stop();
- if(!m_messageHandler->wait(10000))
+ if(!m_messageHandler->wait(2500))
{
m_messageHandler->terminate();
m_messageHandler->wait();
@@ -794,7 +794,7 @@ void MainWindow::dropEvent(QDropEvent *event)
*/
void MainWindow::closeEvent(QCloseEvent *event)
{
- if((m_banner->isVisible() || m_delayedFileTimer->isActive()) && !lamexp_session_ending())
+ if(m_banner->isVisible() || m_delayedFileTimer->isActive())
{
MessageBeep(MB_ICONEXCLAMATION);
event->ignore();
@@ -896,6 +896,31 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event)
return QMainWindow::eventFilter(obj, event);
}
+bool MainWindow::event(QEvent *e)
+{
+ switch(e->type())
+ {
+ case lamexp_event_queryendsession:
+ qWarning("System is shutting down, main window prepares to close...");
+ if(m_banner->isVisible()) m_banner->close();
+ if(m_delayedFileTimer->isActive()) m_delayedFileTimer->stop();
+ return true;
+ case lamexp_event_endsession:
+ qWarning("System is shutting down, main window will close now...");
+ if(isVisible())
+ {
+ while(!close())
+ {
+ QApplication::processEvents(QEventLoop::WaitForMoreEvents & QEventLoop::ExcludeUserInputEvents);
+ }
+ }
+ m_fileListModel->clearFiles();
+ return true;
+ default:
+ return QMainWindow::event(e);
+ }
+}
+
bool MainWindow::winEvent(MSG *message, long *result)
{
return WinSevenTaskbar::handleWinEvent(message, result);
diff --git a/src/Dialog_MainWindow.h b/src/Dialog_MainWindow.h
index ce672129..d7c7fbde 100644
--- a/src/Dialog_MainWindow.h
+++ b/src/Dialog_MainWindow.h
@@ -139,14 +139,15 @@ private slots:
void windowShown(void);
protected:
- void changeEvent(QEvent *e);
- void closeEvent(QCloseEvent *event);
- void dragEnterEvent(QDragEnterEvent *event);
- void dropEvent(QDropEvent *event);
- bool eventFilter(QObject *obj, QEvent *event);
- void resizeEvent(QResizeEvent *event);
- void showEvent(QShowEvent *event);
- bool winEvent(MSG *message, long *result);
+ virtual void changeEvent(QEvent *e);
+ virtual void closeEvent(QCloseEvent *event);
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+ virtual bool eventFilter(QObject *obj, QEvent *event);
+ virtual void resizeEvent(QResizeEvent *event);
+ virtual void showEvent(QShowEvent *event);
+ virtual bool event(QEvent *e);
+ virtual bool winEvent(MSG *message, long *result);
private:
void addFiles(const QStringList &files);
diff --git a/src/Dialog_Processing.cpp b/src/Dialog_Processing.cpp
index cfdc7ed4..ab66acb5 100644
--- a/src/Dialog_Processing.cpp
+++ b/src/Dialog_Processing.cpp
@@ -185,6 +185,7 @@ ProcessingDialog::ProcessingDialog(FileListModel *fileListModel, AudioFileModel
m_succeededJobs.clear();
m_failedJobs.clear();
m_userAborted = false;
+ m_forcedAbort = false;
m_timerStart = 0I64;
}
@@ -276,12 +277,6 @@ void ProcessingDialog::showEvent(QShowEvent *event)
void ProcessingDialog::closeEvent(QCloseEvent *event)
{
- if(lamexp_session_ending() && !m_userAborted)
- {
- qWarning("Computer is shutting down, LameXP will abort and exit!");
- abortEncoding();
- }
-
if(!button_closeDialog->isEnabled())
{
event->ignore();
@@ -321,6 +316,31 @@ bool ProcessingDialog::eventFilter(QObject *obj, QEvent *event)
return false;
}
+bool ProcessingDialog::event(QEvent *e)
+{
+ switch(e->type())
+ {
+ case lamexp_event_queryendsession:
+ qWarning("System is shutting down, preparing to abort...");
+ if(!m_userAborted) abortEncoding(true);
+ return true;
+ case lamexp_event_endsession:
+ qWarning("System is shutting down, encoding will be aborted now...");
+ if(isVisible())
+ {
+ while(!close())
+ {
+ if(!m_userAborted) abortEncoding(true);
+ QApplication::processEvents(QEventLoop::WaitForMoreEvents & QEventLoop::ExcludeUserInputEvents);
+ }
+ }
+ m_pendingJobs.clear();
+ return true;
+ default:
+ return QDialog::event(e);
+ }
+}
+
bool ProcessingDialog::winEvent(MSG *message, long *result)
{
return WinSevenTaskbar::handleWinEvent(message, result);
@@ -338,6 +358,7 @@ void ProcessingDialog::initEncoding(void)
m_succeededJobs.clear();
m_failedJobs.clear();
m_userAborted = false;
+ m_forcedAbort = false;
m_playList.clear();
CHANGE_BACKGROUND_COLOR(frame_header, QColor(Qt::white));
@@ -399,11 +420,11 @@ void ProcessingDialog::initEncoding(void)
}
}
-void ProcessingDialog::abortEncoding(void)
+void ProcessingDialog::abortEncoding(bool force)
{
m_userAborted = true;
+ if(force) m_forcedAbort = true;
button_AbortProcess->setEnabled(false);
-
SET_PROGRESS_TEXT(tr("Aborted! Waiting for running jobs to terminate..."));
for(int i = 0; i < m_threadList.count(); i++)
@@ -429,7 +450,7 @@ void ProcessingDialog::doneEncoding(void)
m_threadList.takeAt(index)->deleteLater();
}
- if(!m_pendingJobs.isEmpty() && !m_userAborted && !lamexp_session_ending())
+ if(!m_pendingJobs.isEmpty() && !m_userAborted)
{
startNextJob();
qDebug("Running jobs: %u", m_runningThreads);
@@ -445,14 +466,14 @@ void ProcessingDialog::doneEncoding(void)
QApplication::setOverrideCursor(Qt::WaitCursor);
qDebug("Running jobs: %u", m_runningThreads);
- if(!m_userAborted && m_settings->createPlaylist() && !m_settings->outputToSourceDir() && !lamexp_session_ending())
+ if(!m_userAborted && m_settings->createPlaylist() && !m_settings->outputToSourceDir())
{
SET_PROGRESS_TEXT(tr("Creating the playlist file, please wait..."));
QApplication::processEvents();
writePlayList();
}
- if(m_userAborted || lamexp_session_ending())
+ if(m_userAborted)
{
CHANGE_BACKGROUND_COLOR(frame_header, QColor("#FFF3BA"));
WinSevenTaskbar::setTaskbarState(this, WinSevenTaskbar::WinSevenTaskbarErrorState);
@@ -461,7 +482,7 @@ void ProcessingDialog::doneEncoding(void)
m_systemTray->showMessage(tr("LameXP - Aborted"), tr("Process was aborted by the user."), QSystemTrayIcon::Warning);
m_systemTray->setIcon(QIcon(":/icons/cd_delete.png"));
QApplication::processEvents();
- if(m_settings->soundsEnabled() && !lamexp_session_ending())
+ if(m_settings->soundsEnabled() && !m_forcedAbort)
{
PlaySound(MAKEINTRESOURCE(IDR_WAVE_ABORTED), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
}
@@ -515,11 +536,7 @@ void ProcessingDialog::doneEncoding(void)
QApplication::restoreOverrideCursor();
- if(lamexp_session_ending())
- {
- accept();
- }
- else if(!m_userAborted && checkBox_shutdownComputer->isChecked())
+ if(!m_userAborted && checkBox_shutdownComputer->isChecked())
{
if(shutdownComputer())
{
diff --git a/src/Dialog_Processing.h b/src/Dialog_Processing.h
index 21e51566..92ed0002 100644
--- a/src/Dialog_Processing.h
+++ b/src/Dialog_Processing.h
@@ -58,7 +58,7 @@ public:
private slots:
void initEncoding(void);
void doneEncoding(void);
- void abortEncoding(void);
+ void abortEncoding(bool force = false);
void processFinished(const QUuid &jobId, const QString &outFileName, bool success);
void progressModelChanged(void);
void logViewDoubleClicked(const QModelIndex &index);
@@ -75,7 +75,8 @@ protected:
void showEvent(QShowEvent *event);
void closeEvent(QCloseEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
- bool winEvent(MSG *message, long *result);
+ virtual bool event(QEvent *e);
+ virtual bool winEvent(MSG *message, long *result);
private:
void setCloseButtonEnabled(bool enabled);
@@ -100,6 +101,7 @@ private:
QList m_succeededJobs;
QList m_failedJobs;
bool m_userAborted;
+ bool m_forcedAbort;
QSystemTrayIcon *m_systemTray;
int m_shutdownFlag;
CPUObserverThread *m_cpuObserver;
diff --git a/src/Dialog_SplashScreen.cpp b/src/Dialog_SplashScreen.cpp
index 6876aa76..cbbea3bd 100644
--- a/src/Dialog_SplashScreen.cpp
+++ b/src/Dialog_SplashScreen.cpp
@@ -149,7 +149,7 @@ void SplashScreen::keyReleaseEvent(QKeyEvent *event)
void SplashScreen::closeEvent(QCloseEvent *event)
{
- if(!m_canClose && !lamexp_session_ending()) event->ignore();
+ if(!m_canClose) event->ignore();
}
bool SplashScreen::winEvent(MSG *message, long *result)
diff --git a/src/Dialog_Update.cpp b/src/Dialog_Update.cpp
index d92a7a7c..f4c73099 100644
--- a/src/Dialog_Update.cpp
+++ b/src/Dialog_Update.cpp
@@ -270,7 +270,7 @@ void UpdateDialog::showEvent(QShowEvent *event)
void UpdateDialog::closeEvent(QCloseEvent *event)
{
- if(!closeButton->isEnabled() && !lamexp_session_ending())
+ if(!closeButton->isEnabled())
{
event->ignore();
}
diff --git a/src/Dialog_WorkingBanner.cpp b/src/Dialog_WorkingBanner.cpp
index e8a8d0a2..1985f491 100644
--- a/src/Dialog_WorkingBanner.cpp
+++ b/src/Dialog_WorkingBanner.cpp
@@ -78,10 +78,11 @@ void WorkingBanner::show(const QString &text)
QApplication::processEvents();
}
-void WorkingBanner::close(void)
+bool WorkingBanner::close(void)
{
m_canClose = true;
- QDialog::close();
+ emit userAbort();
+ return QDialog::close();
}
void WorkingBanner::show(const QString &text, QThread *thread)
@@ -152,7 +153,7 @@ void WorkingBanner::keyReleaseEvent(QKeyEvent *event)
void WorkingBanner::closeEvent(QCloseEvent *event)
{
- if(!m_canClose && !lamexp_session_ending()) event->ignore();
+ if(!m_canClose) event->ignore();
}
bool WorkingBanner::winEvent(MSG *message, long *result)
diff --git a/src/Dialog_WorkingBanner.h b/src/Dialog_WorkingBanner.h
index a7c09b0b..8faf4982 100644
--- a/src/Dialog_WorkingBanner.h
+++ b/src/Dialog_WorkingBanner.h
@@ -38,7 +38,6 @@ public:
void show(const QString &text);
void show(const QString &text, QThread *thread);
void show(const QString &text, QEventLoop *loop);
- void close(void);
private:
QMovie *m_working;
@@ -46,6 +45,7 @@ private:
public slots:
void setText(const QString &text);
+ bool close(void);
signals:
void userAbort(void);
diff --git a/src/Global.cpp b/src/Global.cpp
index 37a3c652..b446a3be 100644
--- a/src/Global.cpp
+++ b/src/Global.cpp
@@ -44,6 +44,7 @@
#include
#include
#include
+#include
//LameXP includes
#include "Resource.h"
@@ -77,13 +78,24 @@ Q_IMPORT_PLUGIN(qsvg)
// TYPES
///////////////////////////////////////////////////////////////////////////////
+static const size_t g_lamexp_ipc_slots = 128;
+
typedef struct
{
unsigned int command;
unsigned int reserved_1;
unsigned int reserved_2;
char parameter[4096];
-} lamexp_ipc_t;
+}
+lamexp_ipc_data_t;
+
+typedef struct
+{
+ unsigned int pos_write;
+ unsigned int pos_read;
+ lamexp_ipc_data_t data[g_lamexp_ipc_slots];
+}
+lamexp_ipc_t;
///////////////////////////////////////////////////////////////////////////////
// GLOBAL VARS
@@ -199,19 +211,25 @@ static const struct
{
char *sharedmem;
char *semaphore_read;
+ char *semaphore_read_mutex;
char *semaphore_write;
+ char *semaphore_write_mutex;
}
g_lamexp_ipc_uuid =
{
"{21A68A42-6923-43bb-9CF6-64BF151942EE}",
"{7A605549-F58C-4d78-B4E5-06EFC34F405B}",
- "{60AA8D04-F6B8-497d-81EB-0F600F4A65B5}"
+ "{60AA8D04-F6B8-497d-81EB-0F600F4A65B5}",
+ "{726061D5-1615-4B82-871C-75FD93458E46}",
+ "{1A616023-AA6A-4519-8AF3-F7736E899977}"
};
static struct
{
QSharedMemory *sharedmem;
QSystemSemaphore *semaphore_read;
+ QSystemSemaphore *semaphore_read_mutex;
QSystemSemaphore *semaphore_write;
+ QSystemSemaphore *semaphore_write_mutex;
}
g_lamexp_ipc_ptr =
{
@@ -227,9 +245,6 @@ static QMutex g_lamexp_message_mutex;
//Main thread ID
static const DWORD g_main_thread_id = GetCurrentThreadId();
-//Session ending flag
-static bool g_sessionIsEnding = false;
-
//Log file
static FILE *g_lamexp_log_file = NULL;
@@ -409,8 +424,9 @@ void lamexp_message_handler(QtMsgType type, const char *msg)
{
static char prefix[] = "DWCF";
int index = qBound(0, static_cast(type), 3);
+ unsigned int timestamp = static_cast(_time64(NULL) % 3600I64);
QString str = QString::fromUtf8(msg).trimmed().replace('\n', '\t');
- fprintf(g_lamexp_log_file, "[%c][%04I64d] %s\r\n", prefix[index], _time64(NULL) % 3600I64, str.toUtf8().constData());
+ fprintf(g_lamexp_log_file, "[%c][%04u] %s\r\n", prefix[index], timestamp, str.toUtf8().constData());
fflush(g_lamexp_log_file);
}
@@ -489,13 +505,16 @@ void lamexp_init_console(int argc, char* argv[])
size_t logfile_len = 0;
if(!_wdupenv_s(&logfile, &logfile_len, L"LAMEXP_LOGFILE"))
{
- FILE *temp = NULL;
- if(!_wfopen_s(&temp, logfile, L"wb"))
+ if(logfile && (logfile_len > 0))
{
- fprintf(temp, "%c%c%c", 0xEF, 0xBB, 0xBF);
- g_lamexp_log_file = temp;
+ FILE *temp = NULL;
+ if(!_wfopen_s(&temp, logfile, L"wb"))
+ {
+ fprintf(temp, "%c%c%c", 0xEF, 0xBB, 0xBF);
+ g_lamexp_log_file = temp;
+ }
+ free(logfile);
}
- free(logfile);
}
}
@@ -813,6 +832,41 @@ QIcon lamexp_app_icon(const QDate *date, const QTime *time)
}
}
+/*
+ * Broadcast event to all windows
+ */
+static bool lamexp_broadcast(int eventType, bool onlyToVisible)
+{
+ if(QApplication *app = dynamic_cast(QApplication::instance()))
+ {
+ qDebug("Broadcasting %d", eventType);
+
+ bool allOk = true;
+ QEvent poEvent(static_cast(eventType));
+ QWidgetList list = app->topLevelWidgets();
+
+ while(!list.isEmpty())
+ {
+ QWidget *widget = list.takeFirst();
+ if(!onlyToVisible || widget->isVisible())
+ {
+ if(!app->sendEvent(widget, &poEvent))
+ {
+ allOk = false;
+ }
+ }
+ }
+
+ qDebug("Broadcast %d done (%s)", eventType, (allOk ? "OK" : "Stopped"));
+ return allOk;
+ }
+ else
+ {
+ qWarning("Broadcast failed, could not get QApplication instance!");
+ return false;
+ }
+}
+
/*
* Qt event filter
*/
@@ -822,33 +876,20 @@ static bool lamexp_event_filter(void *message, long *result)
{
case WM_QUERYENDSESSION:
qWarning("WM_QUERYENDSESSION message received!");
- if(!g_sessionIsEnding)
- {
- g_sessionIsEnding = true;
- if(QApplication *app = reinterpret_cast(QApplication::instance()))
- {
- for(int i = 0; i < 128; i++)
- {
- app->closeAllWindows();
- app->processEvents();
- Sleep(8);
- }
- }
- }
- *result = TRUE;
+ *result = lamexp_broadcast(lamexp_event_queryendsession, false) ? TRUE : FALSE;
return true;
case WM_ENDSESSION:
qWarning("WM_ENDSESSION message received!");
if(reinterpret_cast(message)->wParam == TRUE)
{
- g_sessionIsEnding = true;
+ lamexp_broadcast(lamexp_event_endsession, false);
if(QApplication *app = reinterpret_cast(QApplication::instance()))
{
+ app->closeAllWindows();
app->quit();
- app->processEvents();
- lamexp_finalization();
- exit(1);
}
+ lamexp_finalization();
+ exit(1);
}
*result = 0;
return true;
@@ -1055,19 +1096,23 @@ bool lamexp_init_qt(int argc, char* argv[])
*/
int lamexp_init_ipc(void)
{
- if(g_lamexp_ipc_ptr.sharedmem && g_lamexp_ipc_ptr.semaphore_read && g_lamexp_ipc_ptr.semaphore_write)
+ if(g_lamexp_ipc_ptr.sharedmem && g_lamexp_ipc_ptr.semaphore_read && g_lamexp_ipc_ptr.semaphore_write && g_lamexp_ipc_ptr.semaphore_read_mutex && g_lamexp_ipc_ptr.semaphore_write_mutex)
{
return 0;
}
g_lamexp_ipc_ptr.semaphore_read = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_read), 0);
g_lamexp_ipc_ptr.semaphore_write = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_write), 0);
+ g_lamexp_ipc_ptr.semaphore_read_mutex = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_read_mutex), 0);
+ g_lamexp_ipc_ptr.semaphore_write_mutex = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_write_mutex), 0);
if(g_lamexp_ipc_ptr.semaphore_read->error() != QSystemSemaphore::NoError)
{
QString errorMessage = g_lamexp_ipc_ptr.semaphore_read->errorString();
LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
qFatal("Failed to create system smaphore: %s", errorMessage.toUtf8().constData());
return -1;
}
@@ -1076,6 +1121,28 @@ int lamexp_init_ipc(void)
QString errorMessage = g_lamexp_ipc_ptr.semaphore_write->errorString();
LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+ qFatal("Failed to create system smaphore: %s", errorMessage.toUtf8().constData());
+ return -1;
+ }
+ if(g_lamexp_ipc_ptr.semaphore_read_mutex->error() != QSystemSemaphore::NoError)
+ {
+ QString errorMessage = g_lamexp_ipc_ptr.semaphore_read_mutex->errorString();
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+ qFatal("Failed to create system smaphore: %s", errorMessage.toUtf8().constData());
+ return -1;
+ }
+ if(g_lamexp_ipc_ptr.semaphore_write_mutex->error() != QSystemSemaphore::NoError)
+ {
+ QString errorMessage = g_lamexp_ipc_ptr.semaphore_write_mutex->errorString();
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
qFatal("Failed to create system smaphore: %s", errorMessage.toUtf8().constData());
return -1;
}
@@ -1094,6 +1161,7 @@ int lamexp_init_ipc(void)
else
{
QString errorMessage = g_lamexp_ipc_ptr.sharedmem->errorString();
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
qFatal("Failed to attach to shared memory: %s", errorMessage.toUtf8().constData());
return -1;
}
@@ -1101,13 +1169,16 @@ int lamexp_init_ipc(void)
else
{
QString errorMessage = g_lamexp_ipc_ptr.sharedmem->errorString();
+ LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
qFatal("Failed to create shared memory: %s", errorMessage.toUtf8().constData());
return -1;
}
}
memset(g_lamexp_ipc_ptr.sharedmem->data(), 0, sizeof(lamexp_ipc_t));
- g_lamexp_ipc_ptr.semaphore_write->release();
+ g_lamexp_ipc_ptr.semaphore_write->release(g_lamexp_ipc_slots);
+ g_lamexp_ipc_ptr.semaphore_read_mutex->release();
+ g_lamexp_ipc_ptr.semaphore_write_mutex->release();
return 0;
}
@@ -1117,26 +1188,31 @@ int lamexp_init_ipc(void)
*/
void lamexp_ipc_send(unsigned int command, const char* message)
{
- if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write)
+ if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write || !g_lamexp_ipc_ptr.semaphore_read_mutex || !g_lamexp_ipc_ptr.semaphore_write_mutex)
{
throw "Shared memory for IPC not initialized yet.";
}
- lamexp_ipc_t *lamexp_ipc = new lamexp_ipc_t;
- memset(lamexp_ipc, 0, sizeof(lamexp_ipc_t));
- lamexp_ipc->command = command;
+ lamexp_ipc_data_t ipc_data;
+ memset(&ipc_data, 0, sizeof(lamexp_ipc_data_t));
+ ipc_data.command = command;
+
if(message)
{
- strncpy_s(lamexp_ipc->parameter, 4096, message, _TRUNCATE);
+ strncpy_s(ipc_data.parameter, 4096, message, _TRUNCATE);
}
if(g_lamexp_ipc_ptr.semaphore_write->acquire())
{
- memcpy(g_lamexp_ipc_ptr.sharedmem->data(), lamexp_ipc, sizeof(lamexp_ipc_t));
- g_lamexp_ipc_ptr.semaphore_read->release();
+ if(g_lamexp_ipc_ptr.semaphore_write_mutex->acquire())
+ {
+ lamexp_ipc_t *ptr = reinterpret_cast(g_lamexp_ipc_ptr.sharedmem->data());
+ memcpy(&ptr->data[ptr->pos_write], &ipc_data, sizeof(lamexp_ipc_data_t));
+ ptr->pos_write = (ptr->pos_write + 1) % g_lamexp_ipc_slots;
+ g_lamexp_ipc_ptr.semaphore_read->release();
+ g_lamexp_ipc_ptr.semaphore_write_mutex->release();
+ }
}
-
- LAMEXP_DELETE(lamexp_ipc);
}
/*
@@ -1147,31 +1223,35 @@ void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize)
*command = 0;
message[0] = '\0';
- if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write)
+ if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write || !g_lamexp_ipc_ptr.semaphore_read_mutex || !g_lamexp_ipc_ptr.semaphore_write_mutex)
{
throw "Shared memory for IPC not initialized yet.";
}
- lamexp_ipc_t *lamexp_ipc = new lamexp_ipc_t;
- memset(lamexp_ipc, 0, sizeof(lamexp_ipc_t));
+ lamexp_ipc_data_t ipc_data;
+ memset(&ipc_data, 0, sizeof(lamexp_ipc_data_t));
if(g_lamexp_ipc_ptr.semaphore_read->acquire())
{
- memcpy(lamexp_ipc, g_lamexp_ipc_ptr.sharedmem->data(), sizeof(lamexp_ipc_t));
- g_lamexp_ipc_ptr.semaphore_write->release();
+ if(g_lamexp_ipc_ptr.semaphore_read_mutex->acquire())
+ {
+ lamexp_ipc_t *ptr = reinterpret_cast(g_lamexp_ipc_ptr.sharedmem->data());
+ memcpy(&ipc_data, &ptr->data[ptr->pos_read], sizeof(lamexp_ipc_data_t));
+ ptr->pos_read = (ptr->pos_read + 1) % g_lamexp_ipc_slots;
+ g_lamexp_ipc_ptr.semaphore_write->release();
+ g_lamexp_ipc_ptr.semaphore_read_mutex->release();
- if(!(lamexp_ipc->reserved_1 || lamexp_ipc->reserved_2))
- {
- *command = lamexp_ipc->command;
- strncpy_s(message, buffSize, lamexp_ipc->parameter, _TRUNCATE);
- }
- else
- {
- qWarning("Malformed IPC message, will be ignored");
+ if(!(ipc_data.reserved_1 || ipc_data.reserved_2))
+ {
+ *command = ipc_data.command;
+ strncpy_s(message, buffSize, ipc_data.parameter, _TRUNCATE);
+ }
+ else
+ {
+ qWarning("Malformed IPC message, will be ignored");
+ }
}
}
-
- LAMEXP_DELETE(lamexp_ipc);
}
/*
@@ -1841,19 +1921,13 @@ QStringList lamexp_available_codepages(bool noAliases)
return codecList;
}
-/*
- * Check if the session is about to end
- */
-bool lamexp_session_ending(void)
-{
- return g_sessionIsEnding;
-}
-
/*
* Finalization function (final clean-up)
*/
void lamexp_finalization(void)
{
+ qDebug("lamexp_finalization()");
+
//Free all tools
if(!g_lamexp_tool_registry.isEmpty())
{
diff --git a/src/Global.h b/src/Global.h
index 5df1de48..01b16d1d 100644
--- a/src/Global.h
+++ b/src/Global.h
@@ -71,6 +71,15 @@ typedef enum
}
lamexp_known_folder_t;
+//LameXP user-defined events
+typedef enum
+{
+ lamexp_event = 1000, /*QEvent::User*/
+ lamexp_event_queryendsession = lamexp_event + 666,
+ lamexp_event_endsession = lamexp_event + 667
+}
+lamexp_event_t;
+
//LameXP version info
unsigned int lamexp_version_major(void);
unsigned int lamexp_version_minor(void);
@@ -111,7 +120,6 @@ bool lamexp_portable_mode(void);
bool lamexp_shutdown_computer(const QString &message, const unsigned long timeout = 30, const bool forceShutdown = true, const bool hibernate = false);
bool lamexp_is_hibernation_supported(void);
QIcon lamexp_app_icon(const QDate *date = NULL, const QTime *time = NULL);
-bool lamexp_session_ending(void);
//Translation support
QStringList lamexp_query_translations(void);
diff --git a/src/Main.cpp b/src/Main.cpp
index e66a9261..645f112d 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -153,7 +153,7 @@ static int lamexp_main(int argc, char* argv[])
MainWindow *poMainWindow = new MainWindow(fileListModel, metaInfo, settingsModel);
//Main application loop
- while(bAccepted && (iShutdown <= shutdownFlag_None) && (!lamexp_session_ending()))
+ while(bAccepted && (iShutdown <= shutdownFlag_None))
{
//Show main window
poMainWindow->show();
@@ -161,7 +161,7 @@ static int lamexp_main(int argc, char* argv[])
bAccepted = poMainWindow->isAccepted();
//Show processing dialog
- if(bAccepted && (fileListModel->rowCount() > 0) && (!lamexp_session_ending()))
+ if(bAccepted && (fileListModel->rowCount() > 0))
{
ProcessingDialog *processingDialog = new ProcessingDialog(fileListModel, metaInfo, settingsModel);
processingDialog->exec();
diff --git a/src/Thread_MessageHandler.cpp b/src/Thread_MessageHandler.cpp
index ce0cedc1..99b53224 100644
--- a/src/Thread_MessageHandler.cpp
+++ b/src/Thread_MessageHandler.cpp
@@ -91,7 +91,7 @@ void MessageHandlerThread::stop(void)
if(!m_aborted)
{
m_aborted = true;
- lamexp_ipc_send(0, "");
+ lamexp_ipc_send(0, NULL);
}
}
diff --git a/src/Thread_MessageHandler.h b/src/Thread_MessageHandler.h
index 29d0fee7..ae3c93c3 100644
--- a/src/Thread_MessageHandler.h
+++ b/src/Thread_MessageHandler.h
@@ -35,7 +35,7 @@ public:
private:
char *m_parameter;
- bool m_aborted;
+ volatile bool m_aborted;
signals:
void otherInstanceDetected(void);