Author Topic: Loading a FLAC stream with ReadDirectoryChanges (SOLVED)  (Read 161 times)

dateq

  • Posts: 6
Hey all!

I'm having some great fun with coding with BASS in Rad Studio C++ Builder, but just now I have reached a great big snag. :(

I am trying to load a stream with ReadDirectoryChanges. The function neatly picks up a newly added file to my monitor location and then it should load it into a stream.
For some reason that eludes me, it doesn't work for .flac files. A similar function I created using a FileOpenDialog works perfectly all the time, but the RDC doesn't.
ErrorGetCode keeps giving me error 2

Below a snippet of my code. I really hope someone here can point me in the right direction :)

Code: [Select]
void __fastcall TForm9::ToWav(FILE_NOTIFY_INFORMATION* File)
{
   String FullFileName = OpokaClient.ImportLocation + copyfname(File);
   int BassResult = 0;


   LogLine("File added to: " + FullFileName, apSYSTEM);
   HSTREAM convert = NULL;

   convert = MyBASS_StreamCreateFile(false, FullFileName.c_str(), 0, 0, BASS_STREAM_DECODE | BASS_UNICODE);
   BassResult = MyBASS_ErrorGetCode();

   LogLine("Bass Result: " + IntToStr(BassResult), apSYSTEM);

}
//---------------------------------------------------------------------------

void __fastcall TForm9::Button2Click(TObject *Sender)
{
   String FileName;
   int BassResult = 0;

   if(FileOpenDialog1->Execute()) {
      FileName = FileOpenDialog1->FileName;
   } else {
      LogLine("No file selected. FileName empty", apWARNING);
      return;
   }

   HSTREAM convert = NULL;

   LogLine("ConverterMain: ToWav: FileName: " + FileName, apSYSTEM);

   convert = MyBASS_StreamCreateFile(false, FileName.c_str(), 0, 0, BASS_STREAM_DECODE | BASS_UNICODE);
    BassResult = MyBASS_ErrorGetCode();

   LogLine("chan ErrorCode: " + IntToStr(BassResult), apSYSTEM);

}
//---------------------------------------------------------------------------

copyfname is in a different unit
Code: [Select]
wchar_t* copyfname(FILE_NOTIFY_INFORMATION* pfi)
{

wchar_t* pfn;

pfn = new wchar_t[pfi->FileNameLength+1];

ZeroMemory(pfn, sizeof(wchar_t)*(pfi->FileNameLength+1));
memcpy(pfn, pfi->FileName, pfi->FileNameLength);
return pfn;
}
« Last Edit: 15 Dec '22 - 15:23 by dateq »

Chris

  • Posts: 2132
Re: Loading a FLAC stream with ReadDirectoryChanges
« Reply #1 on: 15 Dec '22 - 13:02 »
is the
Code: [Select]
MyBASS_StreamCreateFilea pseudo for Bass_StreamCreateFile?

Remember to load a Flac Stream you can do it via
e.g
Code: [Select]
BASS_PluginLoad("bassflac.dll", 0);
« Last Edit: 15 Dec '22 - 13:08 by Chris »

dateq

  • Posts: 6
Re: Loading a FLAC stream with ReadDirectoryChanges
« Reply #2 on: 15 Dec '22 - 13:19 »
MyBASS_StreamCreateFile is declared as followed:

Code: [Select]
typedef HSTREAM (CALLBACK* LPFNBASSSTREAMCREATEFILE)( BOOL mem, void *file, QWORD offset, QWORD length, DWORD flags);
LPFNBASSSTREAMCREATEFILE MyBASS_StreamCreateFile;
MyBASS_StreamCreateFile=(LPFNBASSSTREAMCREATEFILE)GetProcAddress(hBassAudio,"BASS_StreamCreateFile");

I tried with and without the PluginLoad, but that makes no difference.
Even without the PluginLoad, the FileOpenDialog button returns ErrorGetCode with 0 upon loading the stream.
There must be something wrong with the FullFileName in the ToWav function, but I am stumped as to what it could be

Ian @ un4seen

  • Administrator
  • Posts: 25059
Re: Loading a FLAC stream with ReadDirectoryChanges
« Reply #3 on: 15 Dec '22 - 13:25 »
Does the FullFileName variable's value include a full path (not relative), and can you successfully use the same variable with another file opening function, eg. CreateFile?

dateq

  • Posts: 6
Re: Loading a FLAC stream with ReadDirectoryChanges
« Reply #4 on: 15 Dec '22 - 13:36 »
Does the FullFileName variable's value include a full path (not relative), and can you successfully use the same variable with another file opening function, eg. CreateFile?
FullFileName is derived from a set importlocation (C:\Projects\Imports\ in this case), the FileName returned from the event of ReadDirectoryChanges is then transformed from a WCHAR to a wchar_t*
(see copyfname function)
All in all, if I upload music.flac to the importlocation, FullFileName reads: C:\Projects\Imports\music.flac which will then be given to StreamCreateFile.

Mind you it is ONLY a flac file that is doing this. if I upload a .mp3 file to the importlocation ErrorGetCode is 0.

If I use the FileOpenDialog in the Button2Click function, it doesn't matter if I select a .mp3 or .flac file. Both are loaded just fine and ErrorGetCode is 0

This is giving me a headache :)

dateq

  • Posts: 6
Re: Loading a FLAC stream with ReadDirectoryChanges
« Reply #5 on: 15 Dec '22 - 14:11 »
As for opening the file with another function,

Code: [Select]
ShellExecuteW(NULL, L"Open", FullFileName.c_str(), NULL, NULL, SW_SHOWNORMAL);
opens the .mp3 and .flac files just fine

Ian @ un4seen

  • Administrator
  • Posts: 25059
Re: Loading a FLAC stream with ReadDirectoryChanges
« Reply #6 on: 15 Dec '22 - 14:50 »
Mind you it is ONLY a flac file that is doing this. if I upload a .mp3 file to the importlocation ErrorGetCode is 0.

If I use the FileOpenDialog in the Button2Click function, it doesn't matter if I select a .mp3 or .flac file. Both are loaded just fine and ErrorGetCode is 0

This is giving me a headache :)

Strange indeed. Is the problem only happening with a particular FLAC file, or all FLAC files? Please check the "convert" variable value too, in case the issue is just that the error code is incorrect.

Btw, I don't think it'll make a difference, but LPFNBASSSTREAMCREATEFILE should really be defined as this (matching the BASS_StreamCreateFile declaration in BASS.H):

Code: [Select]
typedef HSTREAM (WINAPI *LPFNBASSSTREAMCREATEFILE)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);

Note you can avoid needing to redefine the BASS stuff yourself when loading BASS.DLL dynamically, by using "BASSDEF" like this:

Code: [Select]
#define BASSDEF(f) (WINAPI *f) // define the BASS functions as pointers
#include "bass.h"

...

bass = LoadLibrary(basspath);
// import all the BASS functions that are to be used
#define LOADBASSFUNCTION(f) *((void**)&f)=GetProcAddress(bass,#f)
LOADBASSFUNCTION(BASS_Init);
LOADBASSFUNCTION(BASS_StreamCreateFile);
...

dateq

  • Posts: 6
Well, it seems the problem is solved  ;D

After working on it for 2 days now, I realised the one major thing that is different between .mp3 and .flac is size...

When you load a stream via FileOpenDialog, the entire file is still sitting where you want to load it from, but..
Using ReadDirectoryChanges you are reacting to a call that something has changed in a directory. That does NOT mean the entire file is actually there (yet).

With .mp3 files on a m.2 SSD you do not need to worry about it that much. A file of 3 MB takes a millisecond, but a .flac file is 10 times bigger..

I added a very dirty Sleep routine in my code for about 2 seconds. Lo and behold, no problems loading in the .flac stream!