diff --git a/LameXP_VS2010.vcxproj b/LameXP_VS2010.vcxproj index 6e5f8c43..2d3e00f4 100644 --- a/LameXP_VS2010.vcxproj +++ b/LameXP_VS2010.vcxproj @@ -448,6 +448,7 @@ del "$(TargetDir)imageformats\q???d4.dll" + @@ -490,6 +491,7 @@ del "$(TargetDir)imageformats\q???d4.dll" + @@ -681,6 +683,23 @@ del "$(TargetDir)imageformats\q???d4.dll" $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) + + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" + MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" + MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" + MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" + MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" + $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) + $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) + $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) + $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) + $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" @@ -1234,41 +1253,35 @@ del "$(TargetDir)imageformats\q???d4.dll" MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" - "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" - - "$(QTDIR5)\qtbase\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" - "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" - - "$(QTDIR5)\qtbase\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" - "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" - + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" - "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" - - "$(QTDIR5)\qtbase\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" - "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" - - "$(QTDIR5)\qtbase\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp" - "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" - + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)" $(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs) diff --git a/LameXP_VS2010.vcxproj.filters b/LameXP_VS2010.vcxproj.filters index 86432066..95378e26 100644 --- a/LameXP_VS2010.vcxproj.filters +++ b/LameXP_VS2010.vcxproj.filters @@ -358,6 +358,12 @@ Generated Files\MOC + + Source Files\Threads + + + Generated Files\MOC + @@ -662,6 +668,9 @@ Header Files\Threads + + Header Files\Threads + diff --git a/doc/Changelog.html b/doc/Changelog.html index 1e304277..4f5a6435 100644 --- a/doc/Changelog.html +++ b/doc/Changelog.html @@ -20,7 +20,7 @@ a:visited { color: #0000EE; }
  • Added Swedish translation, thanks to Åke Engelbrektson <eson57@gmail.com>
  • Updated mpg123 decoder to v1.14.2 (2012-05-12), compiled with GCC 4.6.1
  • Updated MediaInfo to v0.7.57 (2012-05-02), compiled with ICL 12.1.7 and MSVC 10.0 -
  • Implemented multi-threading in file analyzer for faster file import +
  • Implemented multi-threading in file analyzer for faster file import (about 2.5x to 6.0x faster!)
  • Implemented multi-threading in initialization code for faster application startup
  • Fixed a potential crash (stack overflow) when adding a huge number of files
    diff --git a/etc/Translation/Blank.ts b/etc/Translation/Blank.ts index cb1d314b..fe35926d 100644 --- a/etc/Translation/Blank.ts +++ b/etc/Translation/Blank.ts @@ -776,7 +776,7 @@ - + Show Details @@ -1448,9 +1448,9 @@ - - - + + + Check for Updates @@ -1491,13 +1491,13 @@ - + Disable Update Reminder - + Disable Sound Effects @@ -1577,836 +1577,837 @@ - + + Adding file(s), please wait... - - + + Access Denied - + %1 file(s) have been rejected, because read access was not granted! - + This usually means the file is locked by another process. - + CDDA Files - + %1 file(s) have been rejected, because they are dummy CDDA files! - + Sorry, LameXP cannot extract audio tracks from an Audio-CD at present. - + We recommend using %1 for that purpose. - + Cue Sheet - + %1 file(s) have been rejected, because they appear to be Cue Sheet images! - + Please use LameXP's Cue Sheet wizard for importing Cue Sheet files. - + Files Rejected - + %1 file(s) have been rejected, because the file format could not be recognized! - + This usually means the file is damaged or the file format is not supported. - + Scanning folder(s) for files, please wait... - + DEMO VERSION - + You can drop in audio files here! - + Initializing directory outline, please be patient... - + Open File in External Application - + Browse File Location - + Browse Selected Folder - + Refresh Directory Outline - + Bookmark Current Output Folder - + Export Meta Tags to CSV File - + Import Meta Tags from CSV File - + License Declined - + You have declined the license. Consequently the application will exit now! - + Goodbye! - + LameXP - Expired - + This demo (pre-release) version of LameXP has expired at %1. - + LameXP is free software and release versions won't expire. - - + + Exit Program - + It seems that a bogus anti-virus software is slowing down the startup of LameXP. - + Please refer to the %1 document for details and solutions! - + Slow Startup - - - - - + + + + + Discard - - + + Don't Show Again - + Urgent Update - + Your version of LameXP is more than a year old. Time for an update! - - + + Ignore - + Skipping update check this time, please be patient... - - - + + + Update Reminder - + Your last update check was more than 14 days ago. Check for updates now? - + Your did not check for LameXP updates yet. Check for updates now? - + Postpone - + LameXP detected that your version of the Nero AAC encoder is outdated! - + The current version available is %1 (or later), but you still have version %2 installed. - + n/a - + You can download the latest version of the Nero AAC encoder from the Nero website at: - + (Hint: Please ignore the name of the downloaded ZIP file and check the included 'changelog.txt' instead!) - + AAC Encoder Outdated - + The Nero AAC encoder could not be found. AAC encoding support will be disabled. - + Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory! - + Your LameXP directory is located here: - + You can download the Nero AAC encoder for free from the official Nero website at: - + AAC Support Disabled - - - + + + LameXP - + You must add at least one file to the list before proceeding! - + Not Found - + Your currently selected TEMP folder does not exist anymore: - + Restore Default - + Cancel - + There are less than %1 GB of free diskspace available on your system's TEMP folder. - + It is highly recommend to free up more diskspace before proceeding with the encode! - + Your TEMP folder is located at: - + Low Diskspace Warning - + Abort Encoding Process - + Clean Disk Now - + Low Diskspace - + You are proceeding with low diskspace. Problems might occur! - + Sorry, an unsupported encoder has been chosen! - + Cannot write to the selected output directory. - + Please choose a different directory! - + Load Translation - + Translation Files - + Do you really want to disable the update reminder? - - - - - + + + + - + + Yes - - - - - + + + + - + + No - + The update reminder has been disabled. - + Please remember to check for updates at regular intervals! - + The update reminder has been re-enabled. - + Do you really want to disable all sound effects? - - + + Sound Effects - + All sound effects have been disabled. - + The sound effects have been re-enabled. - - - + + + Nero AAC Notifications - + Do you really want to disable all Nero AAC Encoder notifications? - + All Nero AAC Encoder notifications have been disabled. - + The Nero AAC Encoder notifications have been re-enabled. - - - + + + Slow Startup Notifications - + Do you really want to disable the slow startup notifications? - + The slow startup notifications have been disabled. - + The slow startup notifications have been re-enabled. - - + + Open Cue Sheet - - + + Cue Sheet File - - - + + + Beta Updates - + Do you really want LameXP to check for Beta (pre-release) updates? - + LameXP will check for Beta (pre-release) updates from now on. - + Check Now - + LameXP will <i>not</i> check for Beta (pre-release) updates from now on. - - - + + + Hibernate Computer - + Do you really want the computer to be hibernated on shutdown? - + LameXP will hibernate the computer on shutdown from now on. - + LameXP will <i>not</i> hibernate the computer on shutdown from now on. - - - + + + Shell Integration - + Do you really want to disable the LameXP shell integration? - + The LameXP shell integration has been disabled. - + The LameXP shell integration has been re-enabled. - - + + Add file(s) - - + + Add Folder - - + + Save CSV file - - - - + + + + CSV File - - - - + + + + CSV Export - + Sorry, there are no meta tags that can be exported! - + Sorry, failed to open CSV file for writing! - + Sorry, failed to write to the CSV file! - + The CSV files was created successfully! - - + + Open CSV file - - - - - + + + + + CSV Import - + Sorry, failed to open CSV file for reading! - + Sorry, failed to read from the CSV file! - + Sorry, the CSV file does not contain any known fields! - + CSV file is incomplete. Not all files were updated! - + The CSV files was imported successfully! - - + + New Folder - + Enter the name of the new folder: - + Failed to create folder - + The new folder could not be created: - + Drive is read-only or insufficient access rights! - + QAAC (Apple) - + FHG AAC (Winamp) - + Nero AAC - + Not available! - + Current AAC Encoder: %1 - - - - + + + + Quality Level %1 - - - + + + Compression %1 - - - + + + Uncompressed - + Best Quality (Very Slow) - + High Quality (Recommended) - + Average Quality (Default) - + Low Quality (Fast) - + Poor Quality (Very Fast) - + File name without extension - + Track number with leading zero - + Track title - + Artist name - + Album name - + Year with (at least) four digits - + Comment - + Characters forbidden in file names: - + Rename Macros - + %1 Instance(s) - + Cannot write to the selected directory. Please choose another directory! - + Already Running - + LameXP is already running, please use the running instance! diff --git a/etc/Translation/LameXP_PL.ts b/etc/Translation/LameXP_PL.ts index 2c7d61d4..4bb203a7 100644 --- a/etc/Translation/LameXP_PL.ts +++ b/etc/Translation/LameXP_PL.ts @@ -776,7 +776,7 @@ - + Show Details Pokaż szczegóły @@ -1448,9 +1448,9 @@ - - - + + + Check for Updates Sprawdź aktualizacje @@ -1491,13 +1491,13 @@ - + Disable Update Reminder Wyłącz przypominanie o aktualizacji - + Disable Sound Effects Wyłącz efekty dźwiękowe @@ -1577,836 +1577,837 @@ Hibernuj zamiast zamykać - + + Adding file(s), please wait... Dodawanie plików, prosze czekać... - - + + Access Denied Dostęp zablokowany - + %1 file(s) have been rejected, because read access was not granted! %1 plik(ów) zostało odrzuconych z powodu braku dostępu do pliku! - + This usually means the file is locked by another process. To przeważnie oznacza, że plik jest zablokowany przez inny proces. - + CDDA Files Pliki CDDA - + %1 file(s) have been rejected, because they are dummy CDDA files! %1 plik(ów) zostało odrzuconych ponieważ to nie są właściwe pliki CDDA! - + Sorry, LameXP cannot extract audio tracks from an Audio-CD at present. LameXP nie może teraz wyekstrachować ścieżki z płyty Audio-CD. - + We recommend using %1 for that purpose. Zaleca się użycie w tym celu %1. - + Cue Sheet Cue Sheet - + %1 file(s) have been rejected, because they appear to be Cue Sheet images! %1 plik(ów) zostało odrzuconych, ponieważ to nie są pliki obrazów Cue Sheet! - + Please use LameXP's Cue Sheet wizard for importing Cue Sheet files. Prosze użyć przewodnika Cue Sheet w LameXP w celu importowania tych plików. - + Files Rejected Pliki odrzucone - + %1 file(s) have been rejected, because the file format could not be recognized! %1 plik(ów) zostało odrzuconych, ponieważ ich format nie został rozpoznany! - + This usually means the file is damaged or the file format is not supported. To przeważnie oznacza że plik jest uszkodzony lub format pliku nie jest wspierany. - + Scanning folder(s) for files, please wait... Skanowanie folderu/ów, prosze czekać... - + You can drop in audio files here! Tutaj możesz upuścić pliki dźwiękowe! - + Open File in External Application Otwórz plik w zewnętrznym programie - + Browse File Location Otwórz lokalizację pliku - + Browse Selected Folder Otwórz wybrany folder - + Bookmark Current Output Folder Zapamiętaj wybrany folder - + License Declined Licencja odrzucona - + You have declined the license. Consequently the application will exit now! Odrzuciłeś licencję. W takim razie program zostanie teraz zamknięty! - + Goodbye! Naraska! - + LameXP - Expired LameXP - Termin wygasł - + This demo (pre-release) version of LameXP has expired at %1. Ta wersja demo (beta) LameXP wygasła %1. - + LameXP is free software and release versions won't expire. LameXP jest darmowym oprogramowaniem i pełna wersja nie wygasa. - - + + Exit Program Wyjdź z programu - + It seems that a bogus anti-virus software is slowing down the startup of LameXP. Najwyraźniej twoje oprogramowanie antywirusowe spowalnia uruchamianie się LameXP. - + Please refer to the %1 document for details and solutions! Prosze sprawdzić dokument %1 w celu dalszych szcegółów i rozwiązań! - + Slow Startup Powolny start - - - - - + + + + + Discard Zamknij - - + + Don't Show Again Nie pokazuj ponownie - + Urgent Update Ważna aktualizacja - + Your version of LameXP is more than a year old. Time for an update! Twoja wersja LameXP jest starsza niż rok! Czas na aktualizację! - - - + + + Update Reminder Powiadomienie aktualizacji - + Your last update check was more than 14 days ago. Check for updates now? Ostatnie sprawdzenie aktualizacji było ponad 14 dni temu. Sprawdzić teraz aktualizacje? - + Your did not check for LameXP updates yet. Check for updates now? Nie sprawdzałeś jeszcze aktualizacji LameXP. Sprawdzić teraz aktualizacje? - + Postpone Przełóż - + LameXP detected that your version of the Nero AAC encoder is outdated! LameXP wykrył że Twoja wersja kodera Nero AAC jest nieaktualna! - + The current version available is %1 (or later), but you still have version %2 installed. Wersją dostępną obecnie jest %1, Twoja wersja to %2. - + n/a n/d - + You can download the latest version of the Nero AAC encoder from the Nero website at: Możesz pobrać najnowszą wersję kodera Nero AAC ze strony Nero: - + AAC Encoder Outdated Koder AAC jest nieaktualny - + The Nero AAC encoder could not be found. AAC encoding support will be disabled. Nie można odnaleźć kodera Nero AAC. Kompresja formatu AAC zostanie wyłączona. - + Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory! Prosze skopiować 'neroAacEnc.exe', 'neroAacDec.exe', oraz 'neroAacTag.exe' do folderu LameXP! - + Your LameXP directory is located here: Folder aplikacji LameXP znajduje się tutaj: - + You can download the Nero AAC encoder for free from the official Nero website at: Możesz pobrać koder Nero AAC za darmo z oficjalnej strony Nero: - + AAC Support Disabled Wsparcie dla AAC wyłączone - - - + + + LameXP LameXP - + You must add at least one file to the list before proceeding! Powinienieś dodać przynajmniej jeden plik do listy aby zacząć działać! - + Not Found Nie znaleziono - + Your currently selected TEMP folder does not exist anymore: Wybrany przez Ciebie folder tymczasowy TEMP już nie istnieje: - + Restore Default Przywróć domyślne - + Cancel Anuluj - + Low Diskspace Warning Ostrzeżenie o małej ilości miejsca na dysku - + There are less than %1 GB of free diskspace available on your system's TEMP folder. Jest mniej niż %1 GB dostępnego miejsca w systemowym folderze TEMP. - + DEMO VERSION WERSJA DEMO - + (Hint: Please ignore the name of the downloaded ZIP file and check the included 'changelog.txt' instead!) (Podpowiedź: Zignoruj nazwę pobranego pliku ZIP, w zamian sprawdż załączony w archiwum plik "changelog.txt"!) - + It is highly recommend to free up more diskspace before proceeding with the encode! Jest wysoce zalecane zwolnić miejsce na dysku zanim zaczniesz kompresję! - + Your TEMP folder is located at: Twój folder TEMP znajduję się: - + Abort Encoding Process Przerwij proces kompresji - + Clean Disk Now Wykonaj oczyszczanie dysku - - + + Ignore Ignoruj - + Initializing directory outline, please be patient... Ładowanie zestawu folderów, prosze czekać... - + Refresh Directory Outline Odśwież foldery - + Export Meta Tags to CSV File Eksportuj Tagi do pliku CVS - + Import Meta Tags from CSV File Importuj Tagi do pliku CVS - + Skipping update check this time, please be patient... Pomijanie sprawdzania aktualizacji, prosze czekać... - + Low Diskspace Mało miejsca na dysku - + You are proceeding with low diskspace. Problems might occur! Chcesz zacząć działać z małą ilością miejsca na dysku. Mogą wystąpić problemy! - + Sorry, an unsupported encoder has been chosen! Został wybrany koder, który nie jest wspierany! - + Cannot write to the selected output directory. Nie można zapisać do wybranej lokalizacji. - + Please choose a different directory! Prosze wybrać inną lokalizację! - + Load Translation Zaladuj plik językowy - + Translation Files Pliki językowe - + Do you really want to disable the update reminder? Czy na pewno chcesz wyłączyć przypominanie o aktualizacjach? - - - - - + + + + - + + Yes Tak - - - - - + + + + - + + No Nie - + The update reminder has been disabled. Przypominanie o aktualizacjach wyłączone. - + Please remember to check for updates at regular intervals! Prosze pamiętać o okresowym sprawdzaniu aktualizacji! - + The update reminder has been re-enabled. Przypominanie o aktualizacjach ponownie włączone. - + Do you really want to disable all sound effects? Czy na pewno chcesz wyłączyć wszystkie dźwiękowe? - - + + Sound Effects Efekty dźwiękowe - + All sound effects have been disabled. Wszystkie efekty dźwiękowe zostały wyłączone. - + The sound effects have been re-enabled. Efekty dźwiękowe zostały ponownie włączone. - - - + + + Nero AAC Notifications Powiadomienia Nero AAC - + Do you really want to disable all Nero AAC Encoder notifications? Czy na pewno chcesz wyłączyć wszystkie powiadomienia Nero AAC? - + All Nero AAC Encoder notifications have been disabled. Wszystkie powiadomienia kodera Nero AAC zostały wyłączone. - + The Nero AAC Encoder notifications have been re-enabled. Powiadomienia Nero AAC zostały ponownie włączone. - - - + + + Slow Startup Notifications Powiadomienia o powolnym starcie - + Do you really want to disable the slow startup notifications? Czy na pewno chcesz wyłączyć powiadomienia o powolnym starcie? - + The slow startup notifications have been disabled. Powiadomienia o powolnym starcie zostały wyłączone. - + The slow startup notifications have been re-enabled. Powiadomienia o powolnym starcie zostały ponownie włączone. - - + + Open Cue Sheet Otwórz plik Cue Sheet - - + + Cue Sheet File Plik Cue Sheet - - - + + + Beta Updates Aktualizacje Beta - + Do you really want LameXP to check for Beta (pre-release) updates? Czy na pewno chcesz aby LameXP sprawdzał aktualizacje Beta? - + LameXP will check for Beta (pre-release) updates from now on. Od teraz LameXP będzie sprawdzał aktualizacje Beta. - + Check Now Sprawdź teraz - + LameXP will <i>not</i> check for Beta (pre-release) updates from now on. LameXP od teraz <i>nie będzie</i> sprawdzał aktualizacji Beta. - - - + + + Hibernate Computer Hibernuj komputer - + Do you really want the computer to be hibernated on shutdown? Czy na pewno chcesz aby komputer był hibernowany zamiast zamykany? - + LameXP will hibernate the computer on shutdown from now on. Od teraz LameXP będzie hibernował komputer zamiast zamykać. - + LameXP will <i>not</i> hibernate the computer on shutdown from now on. LameXP od teraz <i>nie</i> będzie hibernował komputera tylko zamykał. - - - + + + Shell Integration Integracja z systemem - + Do you really want to disable the LameXP shell integration? Czy na pewno chcesz wyłączyć integrację LameXP z systemem? - + The LameXP shell integration has been disabled. Integracja LameXP z systemem zostałą wyłączona. - + The LameXP shell integration has been re-enabled. Integracja LameXP z systemem została ponownie włączona. - - + + Add file(s) Dodaj plik(i) - - + + Add Folder Dodaj folder - - + + Save CSV file Zapisz plik CSV - - - - + + + + CSV File Plik CSV - - - - + + + + CSV Export Eksportowanie CSV - + Sorry, there are no meta tags that can be exported! Nie ma żadnych tagów, które można eksportować! - + Sorry, failed to open CSV file for writing! Nie można otworzyć pliku CSV aby go zapisać! - + Sorry, failed to write to the CSV file! Nie można zapisać do pliku CSV! - + The CSV files was created successfully! Pliki CSV utworzone pomyślnie! - - + + Open CSV file Otwórz plik CSV - + Sorry, failed to open CSV file for reading! Nie można otworzyć pliku CSV aby go wczytać! - - - - - + + + + + CSV Import Importowanie CSV - + Sorry, failed to read from the CSV file! Próba odczytania pliku CSV zakończona niepowodzeniem! - + Sorry, the CSV file does not contain any known fields! Plik CSV nie zawiera żadnych znanych pól! - + CSV file is incomplete. Not all files were updated! Plik CSV nie jest kompletny. Nie wszystkie pliki zostały zaktualizowane! - + The CSV files was imported successfully! Pliki CSV zaimportowano pomyślnie! - - + + New Folder Nowy folder - + Enter the name of the new folder: Wprowadź nazwę nowego folderu: - + Failed to create folder Utworzenie folderu zakończone niepowodzeniem - + The new folder could not be created: Nowy folder nie mógł zostać stworzony: - + Drive is read-only or insufficient access rights! Dysk tylko do odczytu lub brak praw dostępu! - + QAAC (Apple) QAAC (Apple) - + FHG AAC (Winamp) FHG AAC (Winamp) - + Nero AAC Nero AAC - + Not available! Niedostępny! - + Current AAC Encoder: %1 Obecny koder AAC: %1 - - - - + + + + Quality Level %1 Poziom jakości %1 - - - + + + Compression %1 Kompresja %1 - - - + + + Uncompressed Nieskompresowany - + Best Quality (Very Slow) Najlepsza jakość (Bardzo wolno) - + High Quality (Recommended) Wysoka jakość (Zalecane) - + Average Quality (Default) Średnia jakość (Domyślnie) - + Low Quality (Fast) Niska jakość (Szybko) - + Poor Quality (Very Fast) Najniższa jakość (Bardzo szybko) - + File name without extension Nazwa pliku bez rozszerzenia - + Track number with leading zero Numer ścieżki z zerem na początku - + Track title Nazwa ścieżki - + Artist name Nazwa Artysty - + Album name Nazwa Albumu - + Year with (at least) four digits Rok z (przynajmniej) czterema cyframi - + Comment Komentarz - + Characters forbidden in file names: Zabronione znaki w nazwach plików: - + Rename Macros Zmień nazwy makr - + %1 Instance(s) %1 wątek/ki - + Cannot write to the selected directory. Please choose another directory! Nie można zapisać do wybranej lokalizacji. Prosze wybierz inną lokalizację! - + Already Running Już działa - + LameXP is already running, please use the running instance! LameXP już działa, przejdź do działającego programu! diff --git a/etc/Translation/LameXP_SV.ts b/etc/Translation/LameXP_SV.ts index 96cd9bc4..8b82990c 100644 --- a/etc/Translation/LameXP_SV.ts +++ b/etc/Translation/LameXP_SV.ts @@ -776,7 +776,7 @@ - + Show Details Visa detaljer @@ -1448,9 +1448,9 @@ - - - + + + Check for Updates Sök efter uppdateringar @@ -1491,13 +1491,13 @@ - + Disable Update Reminder Inaktivera uppdateringsmeddelande - + Disable Sound Effects Inaktivera ljudeffekter @@ -1577,836 +1577,837 @@ Försätt datorn i viloläge vid avslut - + + Adding file(s), please wait... Lägger till fil(er), vänta... - - + + Access Denied Åtkomst nekad - + %1 file(s) have been rejected, because read access was not granted! %1 fil(er) har undantagits, på grund av att åtkomst nekades! - + This usually means the file is locked by another process. Det innebär oftast att filen är låst av någon annan process. - + CDDA Files CDDA-filer - + %1 file(s) have been rejected, because they are dummy CDDA files! %1 fil(er) har undantagits, på grund av att det är fejkade CDDA-filer - + Sorry, LameXP cannot extract audio tracks from an Audio-CD at present. LameXP kan för närvarande inte extrahera ljudspår från en ljud-CD. - + We recommend using %1 for that purpose. Vi rekommenderar att du använder %1 för det ändamålet. - + Cue Sheet Cue-fil - + %1 file(s) have been rejected, because they appear to be Cue Sheet images! %1 fil(er) har undantagits, på grund av att de verkar vara cue-filer! - + Please use LameXP's Cue Sheet wizard for importing Cue Sheet files. Använd LameXPs cue-guide för att importera cue-filer. - + Files Rejected Undantagna filer - + %1 file(s) have been rejected, because the file format could not be recognized! %1 fil(er) har undantagits, på grund av att filformatet inte känns igen! - + This usually means the file is damaged or the file format is not supported. Det innebär oftast att filen är skadad eller att filformatet inte stöds. - + Scanning folder(s) for files, please wait... Genomsöker mapp(ar) efter fil(er), vänta... - + DEMO VERSION DEMOVERSION - + You can drop in audio files here! Du kan dra och släppa filer här! - + Initializing directory outline, please be patient... Initierar mappdisposition, vänta... - + Open File in External Application Öppna fil i externt program - + Browse File Location Öppna målmappen - + Browse Selected Folder Öppna markerad mapp - + Refresh Directory Outline Uppdatera mappdisposition - + Bookmark Current Output Folder Lägg till aktuell utdatamapp i favoriter - + Export Meta Tags to CSV File Exportera metadata till CSV-fil - + Import Meta Tags from CSV File Importera metadata från CSV-fil - + License Declined Licensavtal avvisat - + You have declined the license. Consequently the application will exit now! Du har nekat att godkänna licensavtalet. Programmet kommer nu att avslutas! - + Goodbye! Hej då! - + LameXP - Expired LameXP - Upphört - + This demo (pre-release) version of LameXP has expired at %1. Denna demoversion av LameXP har upphört att gälla från %1. - + LameXP is free software and release versions won't expire. LameXP är kostnadsfritt och release-versionerna upphör inte att gälla. - - + + Exit Program Avsluta programmet - + It seems that a bogus anti-virus software is slowing down the startup of LameXP. Det verkar som ett antivirusprogram orsakar långsammare uppstart av LameXP. - + Please refer to the %1 document for details and solutions! Läs gärna %1 för detaljer och lösningar! - + Slow Startup Långsam uppstart - - - - - + + + + + Discard Stäng - - + + Don't Show Again Visa inte igen - + Urgent Update Viktig uppdatering - + Your version of LameXP is more than a year old. Time for an update! Din version av LameXP är mer än ett år gammal. Dags att uppdatera! - - + + Ignore Ignorera - + Skipping update check this time, please be patient... Hoppar över uppdateringskontrollen den här gången, vänta... - - - + + + Update Reminder Uppdateringspåminnelse - + Your last update check was more than 14 days ago. Check for updates now? Din senaste uppdateringskontroll var för mer än 14 dagar sedan. Vill du söka efter uppdateringar nu? - + Your did not check for LameXP updates yet. Check for updates now? Du har inte genomfört uppdateringskontroll ännu. Vill du söka efter uppdateringar nu? - + Postpone Skjut upp - + LameXP detected that your version of the Nero AAC encoder is outdated! LameXP har uptäckt att din version av Nero AAC-kodare är utdaterad! - + The current version available is %1 (or later), but you still have version %2 installed. Aktuell version är %1 (eller senare), men du har fortfarande version %2. - + n/a n/a - + You can download the latest version of the Nero AAC encoder from the Nero website at: Du kan ladda ner senaste versionen av Nero AAC-kodare från Neros webbsida: - + (Hint: Please ignore the name of the downloaded ZIP file and check the included 'changelog.txt' instead!) (Tips: Bortse från den nedladde zipfilens namn, och kontrollera istället den inkluderade textfilen 'changelog.txt'!) - + AAC Encoder Outdated AAC-kodare utdaterad - + The Nero AAC encoder could not be found. AAC encoding support will be disabled. Neros AAC-kodare kan inte hittas. Stödet för AAC-kodning kommer att inaktiveras. - + Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory! Placera 'neroAacEnc.exe', 'neroAacDec.exe' och 'neroAacTag.exe' i LameXPs programmmapp! - + Your LameXP directory is located here: Din LameXP programmapp finns här: - + You can download the Nero AAC encoder for free from the official Nero website at: Du kan ladda ner Nero AAC-kodare gratis från den officiella webbsidan: - + AAC Support Disabled AAC-stödet är inaktiverat - - - + + + LameXP LameXP - + You must add at least one file to the list before proceeding! Du måste lägga till minst en fil till listan innan du fortsätter! - + Not Found Kan inte hittas - + Your currently selected TEMP folder does not exist anymore: Din aktuella TEMP-mapp finns inte längre: - + Restore Default Återställ standard - + Cancel Avbryt - + There are less than %1 GB of free diskspace available on your system's TEMP folder. Det finns mindre än %1 GB ledigt diskutrymme i systemets temp-mapp. - + It is highly recommend to free up more diskspace before proceeding with the encode! Du behöver frigöra mer diskutrymme innan du fortsätter med omkodningen! - + Your TEMP folder is located at: Temp-mappens placering: - + Low Diskspace Warning Varning för dåligt diskutrymme - + Abort Encoding Process Avbryt omkodningsprocessen - + Clean Disk Now Rensa disken nu - + Low Diskspace Dåligt diskutrymme - + You are proceeding with low diskspace. Problems might occur! Du fortsätter med dåligt diskutrymme. Problem kan uppstå! - + Sorry, an unsupported encoder has been chosen! En kodare som saknar stöd har valts! - + Cannot write to the selected output directory. Kan inte skriva till den valda utdatamappen. - + Please choose a different directory! Välj en annan målmapp! - + Load Translation Läs in översättning - + Translation Files Översättningsfiler - + Do you really want to disable the update reminder? Vill du verkligen inaktivera uppdateringspåminnelsen? - - - - - + + + + - + + Yes Ja - - - - - + + + + - + + No Nej - + The update reminder has been disabled. Uppdateringspåminnelsen har inaktiverats. - + Please remember to check for updates at regular intervals! Glöm inte att söka efter uppdateringar med jämna mellanrum! - + The update reminder has been re-enabled. Uppdateringspåminnelsen har återaktiverats. - + Do you really want to disable all sound effects? Vill du verkligen inaktivera alla ljudeffekter? - - + + Sound Effects Ljudeffekter - + All sound effects have been disabled. Alla ljudeffekter har inaktiverats. - + The sound effects have been re-enabled. Ljudeffekterna har återaktiverats. - - - + + + Nero AAC Notifications Nero AAC-meddelanden - + Do you really want to disable all Nero AAC Encoder notifications? Vill du verkligen inaktivera alla Nero AAC-meddelanden? - + All Nero AAC Encoder notifications have been disabled. Alla Nero AAC-meddelanden har inaktiverats. - + The Nero AAC Encoder notifications have been re-enabled. Nero AAC-meddelanden har återaktiverats. - - - + + + Slow Startup Notifications Meddelande om långsam uppstart - + Do you really want to disable the slow startup notifications? Vill du verkligen inaktivera meddelanden om långsam uppstart? - + The slow startup notifications have been disabled. Meddelanden om långsam uppstart har inaktiverats. - + The slow startup notifications have been re-enabled. Meddelanden om långsam uppstart har återaktiverats. - - + + Open Cue Sheet Öppna cue-fil - - + + Cue Sheet File Cue-fil - - - + + + Beta Updates Beta-uppdateringar - + Do you really want LameXP to check for Beta (pre-release) updates? Vill du verkligen att LameXP skall söka efter beta-uppdateringar? - + LameXP will check for Beta (pre-release) updates from now on. LameXP kommer i fortsättningen att söka efter beta-uppdatyeringar. - + Check Now Sök nu - + LameXP will <i>not</i> check for Beta (pre-release) updates from now on. LameXP kommer i fortsättningen <i>inte</i> att söka efter beta-uppdateringar. - - - + + + Hibernate Computer Viloläge - + Do you really want the computer to be hibernated on shutdown? Vill du verkligen att datorn skall försättas i viloläge vid avslut? - + LameXP will hibernate the computer on shutdown from now on. LameXP kommer i fortsättningen att försätta datorn i viloläge vid avslut. - + LameXP will <i>not</i> hibernate the computer on shutdown from now on. LameXP kommer i fortsättningen <i>inte</i> att försätta datorn i viloläge vid avslut. - - - + + + Shell Integration Utforskarintegrering - + Do you really want to disable the LameXP shell integration? Vill du verkligen inaktivera LameXPs utforskarintegration? - + The LameXP shell integration has been disabled. LameXPs utforskarintegration har inaktiverats. - + The LameXP shell integration has been re-enabled. LameXPs utforskarintegration har återaktiverats. - - + + Add file(s) Lägg till fil(er) - - + + Add Folder Lägg till mapp - - + + Save CSV file Spara CSV-fil - - - - + + + + CSV File CSV-fil - - - - + + + + CSV Export CSV-export - + Sorry, there are no meta tags that can be exported! Det finns ingen meta-data som kan exporteras! - + Sorry, failed to open CSV file for writing! Kunde inte öppna CSV-filen för skrivning! - + Sorry, failed to write to the CSV file! Kunde inte skriva till CSV-filen! - + The CSV files was created successfully! CSV-filen skapades korrekt! - - + + Open CSV file Öppna CSV-fil - - - - - + + + + + CSV Import CSV-import - + Sorry, failed to open CSV file for reading! Kunde inte öppna CSV-filen för läsning! - + Sorry, failed to read from the CSV file! Kunde inte läsa från CSV-filen! - + Sorry, the CSV file does not contain any known fields! CSV-filen innehåller inga kända fält! - + CSV file is incomplete. Not all files were updated! CSV-filen är inte komplett. Alla filer uppdaterades inte! - + The CSV files was imported successfully! CSV-filen importerades korrekt! - - + + New Folder Ny mapp - + Enter the name of the new folder: Namn på den nya mappen: - + Failed to create folder Kunde inte skapa någon mapp - + The new folder could not be created: Den nya mappen kunde inte skapas: - + Drive is read-only or insufficient access rights! Diskenheten är skrivskyddad eller åtkomsträttigheter saknas! - + QAAC (Apple) QAAC (Apple) - + FHG AAC (Winamp) FHG AAC (Winamp) - + Nero AAC Nero AAC - + Not available! Ej tillgänglig! - + Current AAC Encoder: %1 Aktuell AAC-kodare: %1 - - - - + + + + Quality Level %1 Kvallitetsnivå %1 - - - + + + Compression %1 Kompression %1 - - - + + + Uncompressed Okomprimerad - + Best Quality (Very Slow) Bäst kvallitet (långsam) - + High Quality (Recommended) Hög kvallitet (rekommenderas) - + Average Quality (Default) Medelkvallitet (standard) - + Low Quality (Fast) Låg kvallitet (snabb) - + Poor Quality (Very Fast) Dålig kvallitet (mycket snabb) - + File name without extension Filnamn utan filtillägg - + Track number with leading zero Spårnummer med inledande nolla - + Track title Spårtitel - + Artist name Artistnamn - + Album name Albumnamn - + Year with (at least) four digits Årtal med (minst) fyra siffror - + Comment Kommentar - + Characters forbidden in file names: Förbjudna tecken i filnamn: - + Rename Macros Namnändra macron - + %1 Instance(s) %1 instans(er) - + Cannot write to the selected directory. Please choose another directory! Kan inte skriva till den specificerade mappen. Välj en annan destination! - + Already Running Körs redan - + LameXP is already running, please use the running instance! LameXP körs redan, använd den redan startade instansen! diff --git a/src/Config.h b/src/Config.h index 872d5e4f..b25eba2c 100644 --- a/src/Config.h +++ b/src/Config.h @@ -30,7 +30,7 @@ #define VER_LAMEXP_MINOR_LO 5 #define VER_LAMEXP_TYPE Alpha #define VER_LAMEXP_PATCH 2 -#define VER_LAMEXP_BUILD 1023 +#define VER_LAMEXP_BUILD 1026 /////////////////////////////////////////////////////////////////////////////// // Tool versions (minimum expected versions!) diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp index 92a93383..6050ce10 100644 --- a/src/Dialog_MainWindow.cpp +++ b/src/Dialog_MainWindow.cpp @@ -31,6 +31,7 @@ #include "Dialog_DropBox.h" #include "Dialog_CueImport.h" #include "Thread_FileAnalyzer.h" +#include "Thread_FileAnalyzer_ST.h" #include "Thread_MessageHandler.h" #include "Model_MetaInfo.h" #include "Model_Settings.h" @@ -515,6 +516,10 @@ void MainWindow::addFiles(const QStringList &files) tabWidget->setCurrentIndex(0); + int timeMT = 0, timeST = 0; + + //--MT-- + FileAnalyzer *analyzer = new FileAnalyzer(files); connect(analyzer, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection); connect(analyzer, SIGNAL(progressValChanged(unsigned int)), m_banner, SLOT(setProgressVal(unsigned int)), Qt::QueuedConnection); @@ -525,13 +530,44 @@ void MainWindow::addFiles(const QStringList &files) try { m_fileListModel->setBlockUpdates(true); + QTime startTime = QTime::currentTime(); m_banner->show(tr("Adding file(s), please wait..."), analyzer); + timeMT = startTime.secsTo(QTime::currentTime()); } catch(...) { /* ignore any exceptions that may occur */ } + //--ST-- + + FileAnalyzer_ST *analyzerST = new FileAnalyzer_ST(files); + connect(analyzerST, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection); + connect(analyzerST, SIGNAL(progressValChanged(unsigned int)), m_banner, SLOT(setProgressVal(unsigned int)), Qt::QueuedConnection); + connect(analyzerST, SIGNAL(progressMaxChanged(unsigned int)), m_banner, SLOT(setProgressMax(unsigned int)), Qt::QueuedConnection); + connect(analyzerST, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection); + connect(m_banner, SIGNAL(userAbort()), analyzerST, SLOT(abortProcess()), Qt::DirectConnection); + + try + { + m_fileListModel->setBlockUpdates(true); + QTime startTime = QTime::currentTime(); + m_banner->show(tr("Adding file(s), please wait..."), analyzerST); + timeST = startTime.secsTo(QTime::currentTime()); + } + catch(...) + { + /* ignore any exceptions that may occur */ + } + + //------ + + double speedUp = static_cast(timeST) / static_cast(timeMT); + QMessageBox::information(this, "Speed Up", QString().sprintf("Announcement: The new multi-threaded file analyzer is %.1fx faster !!!", speedUp), QMessageBox::Ok); + qWarning("ST: %d, MT: %d", timeST, timeMT); + + //------ + m_fileListModel->setBlockUpdates(false); qApp->processEvents(QEventLoop::ExcludeUserInputEvents); sourceFileView->update(); @@ -557,6 +593,7 @@ void MainWindow::addFiles(const QStringList &files) } LAMEXP_DELETE(analyzer); + LAMEXP_DELETE(analyzerST); m_banner->close(); } diff --git a/src/Dialog_WorkingBanner.cpp b/src/Dialog_WorkingBanner.cpp index bb320043..c60ede8b 100644 --- a/src/Dialog_WorkingBanner.cpp +++ b/src/Dialog_WorkingBanner.cpp @@ -100,6 +100,8 @@ WorkingBanner::~WorkingBanner(void) void WorkingBanner::show(const QString &text) { m_canClose = false; + m_progressInt = -1; + QDialog::show(); setFixedSize(size()); setText(text); diff --git a/src/Thread_FileAnalyzer_ST.cpp b/src/Thread_FileAnalyzer_ST.cpp new file mode 100644 index 00000000..d2352e85 --- /dev/null +++ b/src/Thread_FileAnalyzer_ST.cpp @@ -0,0 +1,825 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2012 LoRd_MuldeR +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +// -------------------------------------------------------------------- +// !!! THIS IS THE OLD SINGLE-THREADED VERSION OF THE FILE ANALYZER !!! +// -------------------------------------------------------------------- + +#include "Thread_FileAnalyzer_ST.h" + +#include "Global.h" +#include "LockedFile.h" +#include "Model_AudioFile.h" +#include "PlaylistImporter.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define IS_KEY(KEY) (key.compare(KEY, Qt::CaseInsensitive) == 0) +#define IS_SEC(SEC) (key.startsWith((SEC "_"), Qt::CaseInsensitive)) +#define FIRST_TOK(STR) (STR.split(" ", QString::SkipEmptyParts).first()) + +//////////////////////////////////////////////////////////// +// Constructor +//////////////////////////////////////////////////////////// + +FileAnalyzer_ST::FileAnalyzer_ST(const QStringList &inputFiles) +: + m_inputFiles(inputFiles), + m_mediaInfoBin(lamexp_lookup_tool("mediainfo.exe")), + m_avs2wavBin(lamexp_lookup_tool("avs2wav.exe")), + m_templateFile(NULL), + m_abortFlag(false) +{ + m_bSuccess = false; + m_bAborted = false; + + if(m_mediaInfoBin.isEmpty()) + { + qFatal("Invalid path to MediaInfo binary. Tool not initialized properly."); + } + + m_filesAccepted = 0; + m_filesRejected = 0; + m_filesDenied = 0; + m_filesDummyCDDA = 0; + m_filesCueSheet = 0; +} + +FileAnalyzer_ST::~FileAnalyzer_ST(void) +{ + if(m_templateFile) + { + QString templatePath = m_templateFile->filePath(); + LAMEXP_DELETE(m_templateFile); + if(QFile::exists(templatePath)) QFile::remove(templatePath); + } +} + +//////////////////////////////////////////////////////////// +// Static data +//////////////////////////////////////////////////////////// + +const char *FileAnalyzer_ST::g_tags_gen[] = +{ + "ID", + "Format", + "Format_Profile", + "Format_Version", + "Duration", + "Title", "Track", + "Track/Position", + "Artist", "Performer", + "Album", + "Genre", + "Released_Date", "Recorded_Date", + "Comment", + "Cover", + "Cover_Type", + "Cover_Mime", + "Cover_Data", + NULL +}; + +const char *FileAnalyzer_ST::g_tags_aud[] = +{ + "ID", + "Source", + "Format", + "Format_Profile", + "Format_Version", + "Channel(s)", + "SamplingRate", + "BitDepth", + "BitRate", + "BitRate_Mode", + NULL +}; + +//////////////////////////////////////////////////////////// +// Thread Main +//////////////////////////////////////////////////////////// + +void FileAnalyzer_ST::run() +{ + m_bSuccess = false; + m_bAborted = false; + + m_filesAccepted = 0; + m_filesRejected = 0; + m_filesDenied = 0; + m_filesDummyCDDA = 0; + m_filesCueSheet = 0; + + m_inputFiles.sort(); + m_recentlyAdded.clear(); + m_abortFlag = false; + + if(!m_templateFile) + { + if(!createTemplate()) + { + qWarning("Failed to create template file!"); + return; + } + } + + while(!m_inputFiles.isEmpty()) + { + int fileType = fileTypeNormal; + QString currentFile = QDir::fromNativeSeparators(m_inputFiles.takeFirst()); + qDebug("Analyzing: %s", currentFile.toUtf8().constData()); + emit fileSelected(QFileInfo(currentFile).fileName()); + AudioFileModel file = analyzeFile(currentFile, &fileType); + + if(m_abortFlag) + { + MessageBeep(MB_ICONERROR); + m_bAborted = true; + qWarning("Operation cancelled by user!"); + return; + } + if(fileType == fileTypeSkip) + { + qWarning("File was recently added, skipping!"); + continue; + } + if(fileType == fileTypeDenied) + { + m_filesDenied++; + qWarning("Cannot access file for reading, skipping!"); + continue; + } + if(fileType == fileTypeCDDA) + { + m_filesDummyCDDA++; + qWarning("Dummy CDDA file detected, skipping!"); + continue; + } + + if(file.fileName().isEmpty() || file.formatContainerType().isEmpty() || file.formatAudioType().isEmpty()) + { + if(PlaylistImporter::importPlaylist(m_inputFiles, currentFile)) + { + qDebug("Imported playlist file."); + } + else if(!QFileInfo(currentFile).suffix().compare("cue", Qt::CaseInsensitive)) + { + qWarning("Cue Sheet file detected, skipping!"); + m_filesCueSheet++; + } + else if(!QFileInfo(currentFile).suffix().compare("avs", Qt::CaseInsensitive)) + { + qDebug("Found a potential Avisynth script, investigating..."); + if(analyzeAvisynthFile(currentFile, file)) + { + m_filesAccepted++; + emit fileAnalyzed(file); + } + else + { + qDebug("Rejected Avisynth file: %s", file.filePath().toUtf8().constData()); + m_filesRejected++; + } + } + else + { + qDebug("Rejected file of unknown type: %s", file.filePath().toUtf8().constData()); + m_filesRejected++; + } + continue; + } + + m_filesAccepted++; + m_recentlyAdded.append(file.filePath()); + emit fileAnalyzed(file); + } + + qDebug("All files added.\n"); + m_bSuccess = true; +} + +//////////////////////////////////////////////////////////// +// Privtae Functions +//////////////////////////////////////////////////////////// + +const AudioFileModel FileAnalyzer_ST::analyzeFile(const QString &filePath, int *type) +{ + *type = fileTypeNormal; + + AudioFileModel audioFile(filePath); + + if(m_recentlyAdded.contains(filePath, Qt::CaseInsensitive)) + { + *type = fileTypeSkip; + return audioFile; + } + + QFile readTest(filePath); + if(!readTest.open(QIODevice::ReadOnly)) + { + *type = fileTypeDenied; + return audioFile; + } + if(checkFile_CDDA(readTest)) + { + *type = fileTypeCDDA; + return audioFile; + } + readTest.close(); + + bool skipNext = false; + unsigned int id_val[2] = {UINT_MAX, UINT_MAX}; + cover_t coverType = coverNone; + QByteArray coverData; + + QStringList params; + params << QString("--Inform=file://%1").arg(QDir::toNativeSeparators(m_templateFile->filePath())); + params << QDir::toNativeSeparators(filePath); + + QProcess process; + process.setProcessChannelMode(QProcess::MergedChannels); + process.setReadChannel(QProcess::StandardOutput); + process.start(m_mediaInfoBin, params); + + if(!process.waitForStarted()) + { + qWarning("MediaInfo process failed to create!"); + qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData()); + process.kill(); + process.waitForFinished(-1); + return audioFile; + } + + while(process.state() != QProcess::NotRunning) + { + if(m_abortFlag) + { + process.kill(); + qWarning("Process was aborted on user request!"); + break; + } + + if(!process.waitForReadyRead()) + { + if(process.state() == QProcess::Running) + { + qWarning("MediaInfo time out. Killing process and skipping file!"); + process.kill(); + process.waitForFinished(-1); + return audioFile; + } + } + + QByteArray data; + + while(process.canReadLine()) + { + QString line = QString::fromUtf8(process.readLine().constData()).simplified(); + if(!line.isEmpty()) + { + //qDebug("Line:%s", line.toUtf8().constData()); + + int index = line.indexOf('='); + if(index > 0) + { + QString key = line.left(index).trimmed(); + QString val = line.mid(index+1).trimmed(); + if(!key.isEmpty()) + { + updateInfo(audioFile, &skipNext, id_val, &coverType, &coverData, key, val); + } + } + } + } + } + + if(audioFile.fileName().isEmpty()) + { + QString baseName = QFileInfo(filePath).fileName(); + int index = baseName.lastIndexOf("."); + + if(index >= 0) + { + baseName = baseName.left(index); + } + + baseName = baseName.replace("_", " ").simplified(); + index = baseName.lastIndexOf(" - "); + + if(index >= 0) + { + baseName = baseName.mid(index + 3).trimmed(); + } + + audioFile.setFileName(baseName); + } + + process.waitForFinished(); + if(process.state() != QProcess::NotRunning) + { + process.kill(); + process.waitForFinished(-1); + } + + if((coverType != coverNone) && (!coverData.isEmpty())) + { + retrieveCover(audioFile, coverType, coverData); + } + + return audioFile; +} + +void FileAnalyzer_ST::updateInfo(AudioFileModel &audioFile, bool *skipNext, unsigned int *id_val, cover_t *coverType, QByteArray *coverData, const QString &key, const QString &value) +{ + //qWarning("'%s' -> '%s'", key.toUtf8().constData(), value.toUtf8().constData()); + + /*New Stream*/ + if(IS_KEY("Gen_ID") || IS_KEY("Aud_ID")) + { + if(value.isEmpty()) + { + *skipNext = false; + } + else + { + //We ignore all ID's, except for the lowest one! + bool ok = false; + unsigned int id = value.toUInt(&ok); + if(ok) + { + if(IS_KEY("Gen_ID")) { id_val[0] = qMin(id_val[0], id); *skipNext = (id > id_val[0]); } + if(IS_KEY("Aud_ID")) { id_val[1] = qMin(id_val[1], id); *skipNext = (id > id_val[1]); } + } + else + { + *skipNext = true; + } + } + if(*skipNext) + { + qWarning("Skipping info for non-primary stream!"); + } + return; + } + + /*Skip or empty?*/ + if((*skipNext) || value.isEmpty()) + { + return; + } + + /*Playlist file?*/ + if(IS_KEY("Aud_Source")) + { + *skipNext = true; + audioFile.setFormatContainerType(QString()); + audioFile.setFormatAudioType(QString()); + qWarning("Skipping info for playlist file!"); + return; + } + + /*General Section*/ + if(IS_SEC("Gen")) + { + if(IS_KEY("Gen_Format")) + { + audioFile.setFormatContainerType(value); + } + else if(IS_KEY("Gen_Format_Profile")) + { + audioFile.setFormatContainerProfile(value); + } + else if(IS_KEY("Gen_Title") || IS_KEY("Gen_Track")) + { + audioFile.setFileName(value); + } + else if(IS_KEY("Gen_Duration")) + { + unsigned int tmp = parseDuration(value); + if(tmp > 0) audioFile.setFileDuration(tmp); + } + else if(IS_KEY("Gen_Artist") || IS_KEY("Gen_Performer")) + { + audioFile.setFileArtist(value); + } + else if(IS_KEY("Gen_Album")) + { + audioFile.setFileAlbum(value); + } + else if(IS_KEY("Gen_Genre")) + { + audioFile.setFileGenre(value); + } + else if(IS_KEY("Gen_Released_Date") || IS_KEY("Gen_Recorded_Date")) + { + unsigned int tmp = parseYear(value); + if(tmp > 0) audioFile.setFileYear(tmp); + } + else if(IS_KEY("Gen_Comment")) + { + audioFile.setFileComment(value); + } + else if(IS_KEY("Gen_Track/Position")) + { + bool ok = false; + unsigned int tmp = value.toUInt(&ok); + if(ok) audioFile.setFilePosition(tmp); + } + else if(IS_KEY("Gen_Cover") || IS_KEY("Gen_Cover_Type")) + { + if(*coverType == coverNone) + { + *coverType = coverJpeg; + } + } + else if(IS_KEY("Gen_Cover_Mime")) + { + QString temp = FIRST_TOK(value); + if(!temp.compare("image/jpeg", Qt::CaseInsensitive)) *coverType = coverJpeg; + else if(!temp.compare("image/png", Qt::CaseInsensitive)) *coverType = coverPng; + else if(!temp.compare("image/gif", Qt::CaseInsensitive)) *coverType = coverGif; + } + else if(IS_KEY("Gen_Cover_Data")) + { + if(!coverData->isEmpty()) coverData->clear(); + coverData->append(QByteArray::fromBase64(FIRST_TOK(value).toLatin1())); + } + else + { + qWarning("Unknown key '%s' with value '%s' found!", key.toUtf8().constData(), value.toUtf8().constData()); + } + return; + } + + /*Audio Section*/ + if(IS_SEC("Aud")) + { + + if(IS_KEY("Aud_Format")) + { + audioFile.setFormatAudioType(value); + } + else if(IS_KEY("Aud_Format_Profile")) + { + audioFile.setFormatAudioProfile(value); + } + else if(IS_KEY("Aud_Format_Version")) + { + audioFile.setFormatAudioVersion(value); + } + else if(IS_KEY("Aud_Channel(s)")) + { + bool ok = false; + unsigned int tmp = value.toUInt(&ok); + if(ok) audioFile.setFormatAudioChannels(tmp); + } + else if(IS_KEY("Aud_SamplingRate")) + { + bool ok = false; + unsigned int tmp = value.toUInt(&ok); + if(ok) audioFile.setFormatAudioSamplerate(tmp); + } + else if(IS_KEY("Aud_BitDepth")) + { + bool ok = false; + unsigned int tmp = value.toUInt(&ok); + if(ok) audioFile.setFormatAudioBitdepth(tmp); + } + else if(IS_KEY("Aud_Duration")) + { + unsigned int tmp = parseDuration(value); + if(tmp > 0) audioFile.setFileDuration(tmp); + } + else if(IS_KEY("Aud_BitRate")) + { + bool ok = false; + unsigned int tmp = value.toUInt(&ok); + if(ok) audioFile.setFormatAudioBitrate(tmp/1000); + } + else if(IS_KEY("Aud_BitRate_Mode")) + { + if(!value.compare("CBR", Qt::CaseInsensitive)) audioFile.setFormatAudioBitrateMode(AudioFileModel::BitrateModeConstant); + if(!value.compare("VBR", Qt::CaseInsensitive)) audioFile.setFormatAudioBitrateMode(AudioFileModel::BitrateModeVariable); + } + else + { + qWarning("Unknown key '%s' with value '%s' found!", key.toUtf8().constData(), value.toUtf8().constData()); + } + return; + } + + /*Section not recognized*/ + qWarning("Unknown section: %s", key.toUtf8().constData()); +} + +bool FileAnalyzer_ST::checkFile_CDDA(QFile &file) +{ + file.reset(); + QByteArray data = file.read(128); + + int i = data.indexOf("RIFF"); + int j = data.indexOf("CDDA"); + int k = data.indexOf("fmt "); + + return ((i >= 0) && (j >= 0) && (k >= 0) && (k > j) && (j > i)); +} + +void FileAnalyzer_ST::retrieveCover(AudioFileModel &audioFile, cover_t coverType, const QByteArray &coverData) +{ + qDebug("Retrieving cover!"); + QString extension; + + switch(coverType) + { + case coverPng: + extension = QString::fromLatin1("png"); + break; + case coverGif: + extension = QString::fromLatin1("gif"); + break; + default: + extension = QString::fromLatin1("jpg"); + break; + } + + if(!(QImage::fromData(coverData, extension.toUpper().toLatin1().constData()).isNull())) + { + QFile coverFile(QString("%1/%2.%3").arg(lamexp_temp_folder2(), lamexp_rand_str(), extension)); + if(coverFile.open(QIODevice::WriteOnly)) + { + coverFile.write(coverData); + coverFile.close(); + audioFile.setFileCover(coverFile.fileName(), true); + } + } + else + { + qWarning("Image data seems to be invalid :-("); + } +} + +bool FileAnalyzer_ST::analyzeAvisynthFile(const QString &filePath, AudioFileModel &info) +{ + QProcess process; + process.setProcessChannelMode(QProcess::MergedChannels); + process.setReadChannel(QProcess::StandardOutput); + process.start(m_avs2wavBin, QStringList() << QDir::toNativeSeparators(filePath) << "?"); + + if(!process.waitForStarted()) + { + qWarning("AVS2WAV process failed to create!"); + qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData()); + process.kill(); + process.waitForFinished(-1); + return false; + } + + bool bInfoHeaderFound = false; + + while(process.state() != QProcess::NotRunning) + { + if(m_abortFlag) + { + process.kill(); + qWarning("Process was aborted on user request!"); + break; + } + + if(!process.waitForReadyRead()) + { + if(process.state() == QProcess::Running) + { + qWarning("AVS2WAV time out. Killing process and skipping file!"); + process.kill(); + process.waitForFinished(-1); + return false; + } + } + + QByteArray data; + + while(process.canReadLine()) + { + QString line = QString::fromUtf8(process.readLine().constData()).simplified(); + if(!line.isEmpty()) + { + int index = line.indexOf(':'); + if(index > 0) + { + QString key = line.left(index).trimmed(); + QString val = line.mid(index+1).trimmed(); + + if(bInfoHeaderFound && !key.isEmpty() && !val.isEmpty()) + { + if(key.compare("TotalSeconds", Qt::CaseInsensitive) == 0) + { + bool ok = false; + unsigned int duration = val.toUInt(&ok); + if(ok) info.setFileDuration(duration); + } + if(key.compare("SamplesPerSec", Qt::CaseInsensitive) == 0) + { + bool ok = false; + unsigned int samplerate = val.toUInt(&ok); + if(ok) info.setFormatAudioSamplerate (samplerate); + } + if(key.compare("Channels", Qt::CaseInsensitive) == 0) + { + bool ok = false; + unsigned int channels = val.toUInt(&ok); + if(ok) info.setFormatAudioChannels(channels); + } + if(key.compare("BitsPerSample", Qt::CaseInsensitive) == 0) + { + bool ok = false; + unsigned int bitdepth = val.toUInt(&ok); + if(ok) info.setFormatAudioBitdepth(bitdepth); + } + } + } + else + { + if(line.contains("[Audio Info]", Qt::CaseInsensitive)) + { + info.setFormatAudioType("Avisynth"); + info.setFormatContainerType("Avisynth"); + bInfoHeaderFound = true; + } + } + } + } + } + + process.waitForFinished(); + if(process.state() != QProcess::NotRunning) + { + process.kill(); + process.waitForFinished(-1); + } + + //Check exit code + switch(process.exitCode()) + { + case 0: + qDebug("Avisynth script was analyzed successfully."); + return true; + break; + case -5: + qWarning("It appears that Avisynth is not installed on the system!"); + return false; + break; + default: + qWarning("Failed to open the Avisynth script, bad AVS file?"); + return false; + break; + } +} + +bool FileAnalyzer_ST::createTemplate(void) +{ + if(m_templateFile) + { + qWarning("Template file already exists!"); + return true; + } + + QString templatePath = QString("%1/%2.txt").arg(lamexp_temp_folder2(), lamexp_rand_str()); + + QFile templateFile(templatePath); + if(!templateFile.open(QIODevice::WriteOnly)) + { + return false; + } + + templateFile.write("General;"); + for(size_t i = 0; g_tags_gen[i]; i++) + { + templateFile.write(QString("Gen_%1=%%1%\\n").arg(g_tags_gen[i]).toLatin1().constData()); + } + templateFile.write("\\n\r\n"); + + templateFile.write("Audio;"); + for(size_t i = 0; g_tags_aud[i]; i++) + { + templateFile.write(QString("Aud_%1=%%1%\\n").arg(g_tags_aud[i]).toLatin1().constData()); + } + templateFile.write("\\n\r\n"); + + bool success = (templateFile.error() == QFile::NoError); + templateFile.close(); + + if(!success) + { + QFile::remove(templatePath); + return false; + } + + try + { + m_templateFile = new LockedFile(templatePath); + } + catch(...) + { + qWarning("Failed to lock template file!"); + return false; + } + + return true; +} + +unsigned int FileAnalyzer_ST::parseYear(const QString &str) +{ + if(str.startsWith("UTC", Qt::CaseInsensitive)) + { + QDate date = QDate::fromString(str.mid(3).trimmed().left(10), "yyyy-MM-dd"); + if(date.isValid()) + { + return date.year(); + } + else + { + return 0; + } + } + else + { + bool ok = false; + int year = str.toInt(&ok); + if(ok && year > 0) + { + return year; + } + else + { + return 0; + } + } +} + +unsigned int FileAnalyzer_ST::parseDuration(const QString &str) +{ + bool ok = false; + unsigned int value = str.toUInt(&ok); + return ok ? (value/1000) : 0; +} + +//////////////////////////////////////////////////////////// +// Public Functions +//////////////////////////////////////////////////////////// + +unsigned int FileAnalyzer_ST::filesAccepted(void) +{ + return m_filesAccepted; +} + +unsigned int FileAnalyzer_ST::filesRejected(void) +{ + return m_filesRejected; +} + +unsigned int FileAnalyzer_ST::filesDenied(void) +{ + return m_filesDenied; +} + +unsigned int FileAnalyzer_ST::filesDummyCDDA(void) +{ + return m_filesDummyCDDA; +} + +unsigned int FileAnalyzer_ST::filesCueSheet(void) +{ + return m_filesCueSheet; +} + +//////////////////////////////////////////////////////////// +// EVENTS +//////////////////////////////////////////////////////////// + +/*NONE*/ diff --git a/src/Thread_FileAnalyzer_ST.h b/src/Thread_FileAnalyzer_ST.h new file mode 100644 index 00000000..4bc87b26 --- /dev/null +++ b/src/Thread_FileAnalyzer_ST.h @@ -0,0 +1,107 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2012 LoRd_MuldeR +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +// -------------------------------------------------------------------- +// !!! THIS IS THE OLD SINGLE-THREADED VERSION OF THE FILE ANALYZER !!! +// -------------------------------------------------------------------- + +#pragma once + +#include +#include + +class AudioFileModel; +class QFile; +class QDir; +class QFileInfo; +class LockedFile; + +//////////////////////////////////////////////////////////// +// Splash Thread +//////////////////////////////////////////////////////////// + +class FileAnalyzer_ST: public QThread +{ + Q_OBJECT + +public: + FileAnalyzer_ST(const QStringList &inputFiles); + ~FileAnalyzer_ST(void); + void run(); + bool getSuccess(void) { return !isRunning() && m_bSuccess; } + unsigned int filesAccepted(void); + unsigned int filesRejected(void); + unsigned int filesDenied(void); + unsigned int filesDummyCDDA(void); + unsigned int filesCueSheet(void); + +signals: + void fileSelected(const QString &fileName); + void fileAnalyzed(const AudioFileModel &file); + +public slots: + void abortProcess(void) { m_abortFlag = true; } + +private: + enum cover_t + { + coverNone, + coverJpeg, + coverPng, + coverGif + }; + enum fileType_t + { + fileTypeNormal = 0, + fileTypeCDDA = 1, + fileTypeDenied = 2, + fileTypeSkip = 3 + }; + + const AudioFileModel analyzeFile(const QString &filePath, int *type); + void updateInfo(AudioFileModel &audioFile, bool *skipNext, unsigned int *id_val, cover_t *coverType, QByteArray *coverData, const QString &key, const QString &value); + unsigned int parseYear(const QString &str); + unsigned int parseDuration(const QString &str); + bool checkFile_CDDA(QFile &file); + void retrieveCover(AudioFileModel &audioFile, cover_t coverType, const QByteArray &coverData); + bool analyzeAvisynthFile(const QString &filePath, AudioFileModel &info); + bool createTemplate(void); + + const QString m_mediaInfoBin; + const QString m_avs2wavBin; + + QStringList m_inputFiles; + QStringList m_recentlyAdded; + unsigned int m_filesAccepted; + unsigned int m_filesRejected; + unsigned int m_filesDenied; + unsigned int m_filesDummyCDDA; + unsigned int m_filesCueSheet; + LockedFile *m_templateFile; + + volatile bool m_abortFlag; + + static const char *g_tags_gen[]; + static const char *g_tags_aud[]; + + bool m_bAborted; + bool m_bSuccess; +}; diff --git a/src/Thread_FileAnalyzer_Task.cpp b/src/Thread_FileAnalyzer_Task.cpp index 74730238..8566b138 100644 --- a/src/Thread_FileAnalyzer_Task.cpp +++ b/src/Thread_FileAnalyzer_Task.cpp @@ -39,22 +39,25 @@ #include #include +#include #define IS_KEY(KEY) (key.compare(KEY, Qt::CaseInsensitive) == 0) #define IS_SEC(SEC) (key.startsWith((SEC "_"), Qt::CaseInsensitive)) #define FIRST_TOK(STR) (STR.split(" ", QString::SkipEmptyParts).first()) /* static vars */ -QReadWriteLock AnalyzeTask::s_lock; QMutex AnalyzeTask::s_waitMutex; QWaitCondition AnalyzeTask::s_waitCond; -unsigned __int64 AnalyzeTask::s_threadIdx_created; -unsigned __int64 AnalyzeTask::s_threadIdx_finished; -unsigned int AnalyzeTask::s_filesAccepted; -unsigned int AnalyzeTask::s_filesRejected; -unsigned int AnalyzeTask::s_filesDenied; -unsigned int AnalyzeTask::s_filesDummyCDDA; -unsigned int AnalyzeTask::s_filesCueSheet; +QSet AnalyzeTask::s_threadIdx_running; +unsigned int AnalyzeTask::s_threadIdx_next = 0; + +/* more static vars */ +QReadWriteLock AnalyzeTask::s_lock; +unsigned int AnalyzeTask::s_filesAccepted = 0; +unsigned int AnalyzeTask::s_filesRejected = 0; +unsigned int AnalyzeTask::s_filesDenied = 0; +unsigned int AnalyzeTask::s_filesDummyCDDA = 0; +unsigned int AnalyzeTask::s_filesCueSheet = 0; QStringList AnalyzeTask::s_additionalFiles; QSet AnalyzeTask::s_recentlyAdded; @@ -84,7 +87,7 @@ AnalyzeTask::AnalyzeTask(const QString &inputFile, const QString &templateFile, AnalyzeTask::~AnalyzeTask(void) { s_waitMutex.lock(); - s_threadIdx_finished = qMax(s_threadIdx_finished, m_threadIdx + 1ui64); + s_threadIdx_running.remove(m_threadIdx); s_waitMutex.unlock(); s_waitCond.wakeAll(); @@ -106,7 +109,7 @@ void AnalyzeTask::run() } s_waitMutex.lock(); - s_threadIdx_finished = qMax(s_threadIdx_finished, m_threadIdx + 1ui64); + s_threadIdx_running.remove(m_threadIdx); s_waitMutex.unlock(); s_waitCond.wakeAll(); @@ -130,7 +133,6 @@ void AnalyzeTask::run_ex(void) } if(fileType == fileTypeSkip) { - waitForPreviousThreads(); qWarning("File was recently added, skipping!"); return; } @@ -139,7 +141,6 @@ void AnalyzeTask::run_ex(void) QWriteLocker lock(&s_lock); s_filesDenied++; lock.unlock(); - waitForPreviousThreads(); qWarning("Cannot access file for reading, skipping!"); return; } @@ -148,7 +149,6 @@ void AnalyzeTask::run_ex(void) QWriteLocker lock(&s_lock); s_filesDummyCDDA++; lock.unlock(); - waitForPreviousThreads(); qWarning("Dummy CDDA file detected, skipping!"); return; } @@ -159,7 +159,6 @@ void AnalyzeTask::run_ex(void) QStringList fileList; if(PlaylistImporter::importPlaylist(fileList, currentFile)) { - waitForPreviousThreads(); qDebug("Imported playlist file."); QWriteLocker lock(&s_lock); s_additionalFiles << fileList; @@ -195,7 +194,6 @@ void AnalyzeTask::run_ex(void) qDebug("Rejected file of unknown type: %s", file.filePath().toUtf8().constData()); s_filesRejected++; } - waitForPreviousThreads(); return; } @@ -725,7 +723,8 @@ unsigned int AnalyzeTask::parseDuration(const QString &str) unsigned __int64 AnalyzeTask::makeThreadIdx(void) { s_waitMutex.lock(); - unsigned __int64 idx = s_threadIdx_created++; + unsigned int idx = s_threadIdx_next++; + s_threadIdx_running.insert(idx); s_waitMutex.unlock(); return idx; @@ -736,13 +735,20 @@ void AnalyzeTask::waitForPreviousThreads(void) //This function will block until all threads with a *lower* index have terminated. //Required to make sure that the files will be added in the "correct" order! + s_waitMutex.lock(); int retryCount = 0; - while(retryCount < MAX_RETRIES) + forever { - s_waitMutex.lock(); + bool bWaitFlag = false; + QSet::const_iterator i; - if((s_threadIdx_finished >= m_threadIdx) || *m_abortFlag) + for(i = s_threadIdx_running.begin(); i != s_threadIdx_running.end(); ++i) + { + if(*i < m_threadIdx) { bWaitFlag = true; break; } + } + + if((!bWaitFlag) || *m_abortFlag) { s_waitMutex.unlock(); return; @@ -750,13 +756,13 @@ void AnalyzeTask::waitForPreviousThreads(void) if(!s_waitCond.wait(&s_waitMutex, WAITCOND_TIMEOUT)) { - retryCount++; + if(++retryCount > MAX_RETRIES) + { + qWarning("AnalyzeTask::waitForPreviousThreads encountered timeout !!!"); + s_threadIdx_running.clear(); + } } - - s_waitMutex.unlock(); } - - qWarning("AnalyzeTask Timeout, will proceed anyway !!!"); } //////////////////////////////////////////////////////////// @@ -835,8 +841,8 @@ void AnalyzeTask::reset(void) lock.unlock(); s_waitMutex.lock(); - s_threadIdx_created = 0; - s_threadIdx_finished = 0; + s_threadIdx_next = 0; + s_threadIdx_running.clear(); s_waitMutex.unlock(); } diff --git a/src/Thread_FileAnalyzer_Task.h b/src/Thread_FileAnalyzer_Task.h index e1135074..ac91aaaa 100644 --- a/src/Thread_FileAnalyzer_Task.h +++ b/src/Thread_FileAnalyzer_Task.h @@ -102,8 +102,8 @@ private: static QMutex s_waitMutex; static QWaitCondition s_waitCond; - static unsigned __int64 s_threadIdx_created; - static unsigned __int64 s_threadIdx_finished; + static QSet s_threadIdx_running; + static unsigned int s_threadIdx_next; static QReadWriteLock s_lock; static unsigned int s_filesAccepted;