avoid memory leak at sound play

Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
This commit is contained in:
Sergey Isakov 2020-04-15 12:13:51 +03:00
parent 1f85d633c4
commit 0733b704ff
6 changed files with 64 additions and 42 deletions

View File

@ -3739,8 +3739,8 @@ XTheme::GetThemeTagSettings (void* DictP)
#if XCINEMA #if XCINEMA
Dict = GetProperty (DictPointer, "Anime"); Dict = GetProperty (DictPointer, "Anime");
if (Dict != NULL) { if (Dict != NULL) {
INTN i, Count = GetTagCount (Dict); INTN Count = GetTagCount (Dict);
for (i = 0; i < Count; i++) { for (INTN i = 0; i < Count; i++) {
FILM *NewFilm = new FILM(); FILM *NewFilm = new FILM();
if (EFI_ERROR (GetElement (Dict, i, &Dict3))) { if (EFI_ERROR (GetElement (Dict, i, &Dict3))) {
continue; continue;
@ -3797,10 +3797,13 @@ XTheme::GetThemeTagSettings (void* DictP)
Dict2 = GetProperty (Dict3, "Once"); Dict2 = GetProperty (Dict3, "Once");
NewFilm->RunOnce = IsPropertyTrue (Dict2); NewFilm->RunOnce = IsPropertyTrue (Dict2);
NewFilm->GetFrames(ThemeX); //used properties: ID, Path, NumFrames
ThemeX.Cinema.AddFilm(NewFilm); ThemeX.Cinema.AddFilm(NewFilm);
// delete NewFilm; //looks like already deleted // delete NewFilm; //looks like already deleted
} }
} }
#else #else
Dict = GetProperty (DictPointer, "Anime"); Dict = GetProperty (DictPointer, "Anime");
@ -4165,7 +4168,7 @@ finish:
Status = StartupSoundPlay(ThemeX.ThemeDir, NULL); Status = StartupSoundPlay(ThemeX.ThemeDir, NULL);
} else { // theme loaded successfully } else { // theme loaded successfully
ThemeX.embedded = false; ThemeX.embedded = false;
ThemeX.Theme.takeValueFrom(GlobalConfig.Theme); ThemeX.Theme.takeValueFrom(GlobalConfig.Theme); //XStringW from CHAR16*)
// read theme settings // read theme settings
if (!ThemeX.TypeSVG) { if (!ThemeX.TypeSVG) {
TagPtr DictPointer = GetProperty(ThemeDict, "Theme"); TagPtr DictPointer = GetProperty(ThemeDict, "Theme");

View File

@ -69,25 +69,34 @@ StartupSoundPlay(EFI_FILE *Dir, CONST CHAR16* SoundFile)
UINT8 OutputIndex = (OldChosenAudio & 0xFF); UINT8 OutputIndex = (OldChosenAudio & 0xFF);
UINT8 OutputVolume = DefaultAudioVolume; UINT8 OutputVolume = DefaultAudioVolume;
UINT16 *TempData = NULL; UINT16 *TempData = NULL;
BOOLEAN AllocAsPage = FALSE;
if (!AudioIo) {
Status = EFI_DEVICE_ERROR;
// DBG("not found AudioIo to play\n");
goto DONE_ERROR;
}
if (SoundFile) { if (SoundFile) {
Status = egLoadFile(Dir, SoundFile, &FileData, &FileDataLength); Status = egLoadFile(Dir, SoundFile, &FileData, &FileDataLength);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DBG("file sound read: %ls %s\n", SoundFile, strerror(Status)); // DBG("file sound read: %ls %s\n", SoundFile, strerror(Status));
return Status; return Status;
} }
} else { } else {
FileData = EmbeddedSound; FileData = EmbeddedSound;
FileDataLength = EmbeddedSoundLength; FileDataLength = EmbeddedSoundLength;
DBG("got embedded sound\n"); // DBG("got embedded sound\n");
} }
WaveData.Samples = NULL; WaveData.Samples = NULL;
Status = WaveGetFileData(FileData, (UINT32)FileDataLength, &WaveData); Status = WaveGetFileData(FileData, (UINT32)FileDataLength, &WaveData); //
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
MsgLog(" wrong sound file, wave status=%s\n", strerror(Status)); MsgLog(" wrong sound file, wave status=%s\n", strerror(Status));
//if error then data not allocated
return Status; return Status;
} }
AllocAsPage = TRUE;
MsgLog(" Channels: %u Sample rate: %u Hz Bits: %u\n", WaveData.Format->Channels, WaveData.Format->SamplesPerSec, WaveData.Format->BitsPerSample); MsgLog(" Channels: %u Sample rate: %u Hz Bits: %u\n", WaveData.Format->Channels, WaveData.Format->SamplesPerSec, WaveData.Format->BitsPerSample);
EFI_AUDIO_IO_PROTOCOL_BITS bits; EFI_AUDIO_IO_PROTOCOL_BITS bits;
@ -108,7 +117,7 @@ StartupSoundPlay(EFI_FILE *Dir, CONST CHAR16* SoundFile)
bits = EfiAudioIoBits32; bits = EfiAudioIoBits32;
break; break;
default: default:
return EFI_UNSUPPORTED; goto DONE_ERROR;
} }
EFI_AUDIO_IO_PROTOCOL_FREQ freq; EFI_AUDIO_IO_PROTOCOL_FREQ freq;
@ -144,14 +153,14 @@ StartupSoundPlay(EFI_FILE *Dir, CONST CHAR16* SoundFile)
freq = EfiAudioIoFreq192kHz; freq = EfiAudioIoFreq192kHz;
break; break;
default: default:
return EFI_UNSUPPORTED; goto DONE_ERROR;
} }
DBG("output to channel %d with volume %d, len=%d\n", OutputIndex, OutputVolume, WaveData.SamplesLength); DBG("output to channel %d with volume %d, len=%d\n", OutputIndex, OutputVolume, WaveData.SamplesLength);
DBG(" sound channels=%d bits=%d freq=%d\n", WaveData.Format->Channels, WaveData.Format->BitsPerSample, WaveData.Format->SamplesPerSec); DBG(" sound channels=%d bits=%d freq=%d\n", WaveData.Format->Channels, WaveData.Format->BitsPerSample, WaveData.Format->SamplesPerSec);
if (!WaveData.SamplesLength || !OutputVolume) { if (!WaveData.SamplesLength || !OutputVolume) {
// DBG("nothing to play\n"); // DBG("nothing to play\n"); //but data allocated
Status = EFI_NOT_FOUND; Status = EFI_NOT_FOUND;
goto DONE_ERROR; goto DONE_ERROR;
} }
@ -185,16 +194,11 @@ StartupSoundPlay(EFI_FILE *Dir, CONST CHAR16* SoundFile)
WaveData.SamplesLength *= 6; WaveData.SamplesLength *= 6;
DBG("sound converted to 48kHz\n"); DBG("sound converted to 48kHz\n");
WaveData.Samples = (UINT8*)TempData; WaveData.Samples = (UINT8*)TempData;
AllocAsPage = FALSE;
} else { } else {
TempData = (UINT16*)WaveData.Samples; TempData = (UINT16*)WaveData.Samples;
} }
if (!AudioIo) {
Status = EFI_DEVICE_ERROR;
// DBG("not found AudioIo to play\n");
goto DONE_ERROR;
}
// Setup playback. // Setup playback.
if (OutputIndex > AudioNum) { if (OutputIndex > AudioNum) {
OutputIndex = 0; OutputIndex = 0;
@ -210,13 +214,13 @@ StartupSoundPlay(EFI_FILE *Dir, CONST CHAR16* SoundFile)
// Start playback. // Start playback.
if (gSettings.PlayAsync) { if (gSettings.PlayAsync) {
Status = AudioIo->StartPlaybackAsync(AudioIo, (UINT8*)TempData, WaveData.SamplesLength, 0, NULL, NULL); Status = AudioIo->StartPlaybackAsync(AudioIo, (UINT8*)TempData, WaveData.SamplesLength, 0, NULL, NULL);
DBG("async started, status=%s\n", strerror(Status)); // DBG("async started, status=%s\n", strerror(Status));
} else { } else {
Status = AudioIo->StartPlayback(AudioIo, (UINT8*)TempData, WaveData.SamplesLength, 0); Status = AudioIo->StartPlayback(AudioIo, (UINT8*)TempData, WaveData.SamplesLength, 0);
// DBG("sync started, status=%s\n", strerror(Status)); // DBG("sync started, status=%s\n", strerror(Status));
if (!EFI_ERROR(Status)) { // if (!EFI_ERROR(Status)) {
FreePool(TempData); // FreePool(TempData);
} // }
} }
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
@ -224,10 +228,20 @@ StartupSoundPlay(EFI_FILE *Dir, CONST CHAR16* SoundFile)
} }
DONE_ERROR: DONE_ERROR:
// here we have memory leak with TempData == WaveData.Samples
// TempData allocated as AllocatePool while Samples allocated as AllocatePages
// and we can't keep the info up to stop AsyncPlay
if (FileData && SoundFile) { //dont free embedded sound if (FileData && SoundFile) { //dont free embedded sound
// DBG("free sound\n"); // DBG("free sound\n");
FreePool(FileData); FreePool(FileData);
} }
if (!gSettings.PlayAsync) { //dont free sound when async play
if (AllocAsPage) {
FreePages(WaveData.Samples,EFI_SIZE_TO_PAGES(WaveData.SamplesLength+4095));
} else {
FreePool(TempData);
}
}
DBG("sound play end with status=%s\n", strerror(Status)); DBG("sound play end with status=%s\n", strerror(Status));
return Status; return Status;
} }

View File

@ -11,17 +11,20 @@
#include "XCinema.h" #include "XCinema.h"
#include "../gui/REFIT_MENU_SCREEN.h" #include "../gui/REFIT_MENU_SCREEN.h"
#ifndef DEBUG_ALL
#define DEBUG_CINEMA 1
#else
#define DEBUG_CINEMA DEBUG_ALL
#endif
#if DEBUG_CINEMA == 0
#define DBG(...)
#else
#define DBG(...) DebugLog(DEBUG_CINEMA, __VA_ARGS__)
#endif
//Screen.UpdateAnime(); called from Menu cycle wait for event //Screen.UpdateAnime(); called from Menu cycle wait for event
//Now = AsmReadTsc();
//if (TimeDiff(LastDraw, Now) < FrameTime) return;
//if (Film[CurrentFrame]) { Draw }
// else skip draw
// CurrentFrame++;
//if (CurrentFrame >= Frames) {
// AnimeRun = !Once;
// CurrentFrame = 0;
//}
//LastDraw = Now;
// object XCinema::Cinema is a part of Theme // object XCinema::Cinema is a part of Theme
// object FILM::FilmX is a part or current Screen. Must be initialized from Cinema somewhere on Screen init // object FILM::FilmX is a part or current Screen. Must be initialized from Cinema somewhere on Screen init
@ -51,7 +54,9 @@ VOID REFIT_MENU_SCREEN::UpdateFilm()
#endif #endif
FILM* XCinema::GetFilm(INTN Id) FILM* XCinema::GetFilm(INTN Id)
{ {
DBG("ask film %lld\n", Id);
for (size_t i = 0; i < Cinema.size(); ++i) { for (size_t i = 0; i < Cinema.size(); ++i) {
DBG("check film %lld\n", Cinema[i].GetIndex());
if (Cinema[i].GetIndex() == Id) { if (Cinema[i].GetIndex() == Id) {
return &Cinema[i]; return &Cinema[i];
} }
@ -67,8 +72,10 @@ void XCinema::AddFilm(FILM* NewFilm)
static XImage NullImage; static XImage NullImage;
const XImage& FILM::GetImage(INTN Index) const const XImage& FILM::GetImage(INTN Index) const
{ {
DBG("ask for frame #%lld\n", Index);
for (size_t i = 0; i < Frames.size(); ++i) { for (size_t i = 0; i < Frames.size(); ++i) {
if (Frames[i].getIndex() == Index) { if (Frames[i].getIndex() == Index) {
DBG("...found\n");
return Frames[i].getImage(); return Frames[i].getImage();
} }
} }
@ -85,7 +92,6 @@ const XImage& FILM::GetImage() const
return NullImage; return NullImage;
} }
void FILM::AddFrame(XImage* Frame, INTN Index) void FILM::AddFrame(XImage* Frame, INTN Index)
{ {
IndexedImage* NewFrame = new IndexedImage(Index); IndexedImage* NewFrame = new IndexedImage(Index);
@ -107,9 +113,11 @@ void FILM::GetFrames(XTheme& TheTheme /*, const XStringW& Path*/) // Path alread
Status = TheTheme.LoadSvgFrame(Index, &NewImage); Status = TheTheme.LoadSvgFrame(Index, &NewImage);
} else { } else {
XStringW Name = SWPrintf("%ls\\%ls_%03lld.png", Path.wc_str(), Path.wc_str(), Index); XStringW Name = SWPrintf("%ls\\%ls_%03lld.png", Path.wc_str(), Path.wc_str(), Index);
// DBG("try to load %ls\n", Name.wc_str()); //fine
if (FileExists(ThemeDir, Name.wc_str())) { if (FileExists(ThemeDir, Name.wc_str())) {
Status = NewImage.LoadXImage(ThemeDir, Name); Status = NewImage.LoadXImage(ThemeDir, Name);
} }
// DBG(" read status=%s\n", strerror(Status));
} }
if (!EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
AddFrame(&NewImage, Index); AddFrame(&NewImage, Index);

View File

@ -10,7 +10,7 @@
#include "../refit/menu.h" #include "../refit/menu.h"
#ifndef DEBUG_ALL #ifndef DEBUG_ALL
#define DEBUG_MOUSE 1 #define DEBUG_MOUSE 0
#else #else
#define DEBUG_MOUSE DEBUG_ALL #define DEBUG_MOUSE DEBUG_ALL
#endif #endif

View File

@ -2861,7 +2861,7 @@ static void nsvg__parseText(NSVGparser* p, const char** dict)
fontChain = fontChain->next; fontChain = fontChain->next;
} }
if (!fontChain && fontChainSimilar) { //font with this style is not found but we have same font with other style if (!fontChain && fontChainSimilar) { //font with this style is not found but we have same font with other style
DBG("found similar font with style=%c\n", fontChainSimilar->font->fontStyle); // DBG("found similar font with style=%c\n", fontChainSimilar->font->fontStyle);
fontChain = fontChainSimilar; fontChain = fontChainSimilar;
fontSVG = fontChain->font; fontSVG = fontChain->font;
} }
@ -2871,13 +2871,11 @@ static void nsvg__parseText(NSVGparser* p, const char** dict)
UINTN FileDataLength = 0; UINTN FileDataLength = 0;
NSVGparser *p1 = NULL; NSVGparser *p1 = NULL;
EFI_STATUS Status; EFI_STATUS Status;
DBG("required font %s not found, try to load external\n", text->fontFace->fontFamily); // DBG("required font %s not found, try to load external\n", text->fontFace->fontFamily);
// CONST CHAR16 *FontFileName = PoolPrint(L"%a.svg", text->fontFace->fontFamily);
XStringW FontFileName = XStringW().takeValueFrom(text->fontFace->fontFamily) + L".svg"_XSW; XStringW FontFileName = XStringW().takeValueFrom(text->fontFace->fontFamily) + L".svg"_XSW;
DBG(" file name =%ls\n", FontFileName.wc_str()); // DBG(" file name =%ls\n", FontFileName.wc_str());
Status = egLoadFile(ThemeX.ThemeDir, FontFileName.wc_str(), &FileData, &FileDataLength); Status = egLoadFile(ThemeX.ThemeDir, FontFileName.wc_str(), &FileData, &FileDataLength);
// FreePool(FontFileName); // DBG(" font %s loaded status=%lld, %s\n", text->fontFace->fontFamily, Status, strerror(Status));
DBG(" font %s loaded status=%lld, %s\n", text->fontFace->fontFamily, Status, strerror(Status));
if (!EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
p1 = nsvgParse((CHAR8*)FileData, 72, 1.0f); //later we will free parser p1 p1 = nsvgParse((CHAR8*)FileData, 72, 1.0f); //later we will free parser p1
if (!p1) { if (!p1) {
@ -2923,7 +2921,7 @@ static void nsvg__parseText(NSVGparser* p, const char** dict)
textFace[1].size = (INTN)text->fontSize; textFace[1].size = (INTN)text->fontSize;
textFace[1].color = text->fontColor; textFace[1].color = text->fontColor;
textFace[1].valid = TRUE; textFace[1].valid = TRUE;
DBG("set message->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize); DBG("set message_night->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
break; break;
} else if (strcmp(group->id, "MenuRows") == 0) { } else if (strcmp(group->id, "MenuRows") == 0) {
if (!textFace[2].valid) { if (!textFace[2].valid) {
@ -2954,15 +2952,12 @@ static void nsvg__parseText(NSVGparser* p, const char** dict)
textFace[0].size = (INTN)text->fontSize; textFace[0].size = (INTN)text->fontSize;
textFace[0].color = text->fontColor; textFace[0].color = text->fontColor;
textFace[0].valid = TRUE; textFace[0].valid = TRUE;
DBG("set help->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize); DBG("set help_night->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
break; break;
} }
group = group->next; group = group->next;
} }
} }
// if ((!text->font || !text->font->glyphs) && fontsDB) {
// text->font = fontsDB->font; //first found
// }
//add to head //add to head
text->next = p->text; text->next = p->text;

View File

@ -482,11 +482,13 @@ INTN HybridRepositioning(INTN Edge, INTN Value, INTN ImageDimension, INTN Screen
BOOLEAN REFIT_MENU_SCREEN::GetAnime() BOOLEAN REFIT_MENU_SCREEN::GetAnime()
{ {
FilmC = ThemeX.Cinema.GetFilm(ID); FilmC = ThemeX.Cinema.GetFilm(ID);
DBG("ScreenID=%lld Film found=%d\n", ID, (FilmC != nullptr)?1:0);
return FilmC != nullptr; return FilmC != nullptr;
} }
VOID REFIT_MENU_SCREEN::InitAnime() VOID REFIT_MENU_SCREEN::InitAnime()
{ {
if (FilmC && (FilmC->FilmX >=0) && (FilmC->FilmX <=100) && if (FilmC && (FilmC->FilmX >=0) && (FilmC->FilmX <=100) &&
(FilmC->FilmY >=0) && (FilmC->FilmY <=100)) { (FilmC->FilmY >=0) && (FilmC->FilmY <=100)) {
// Check if screen size being used is different from theme origination size. // Check if screen size being used is different from theme origination size.