I want use my own file system to manage FMOD bank resources. My FileSystem can provide a stream for runtimanager.
‘loadBankCustom’ can load bank data with open, seek, read, close callbacks.But I did not really understand the correct method to use it.
1、What does BANK_INFO’s userdata refer to? Is a pointer to the bank resource data provided by my file system? In my case, should I convert my stream to IntPtr and assign it to UserData? When I did this, my program crashed.
2、My understanding of each callback is to open, seek, read, or close a stream or file in a callback. Is it correct?
3、What is the relationship between Handle and UserData in those callbacks? for example, in the FILE_OPEN_CALLBACK, (ref IntPtr handle, IntPtr userdata)
My example:
// get a stream from filesystem
Stream fmodStream = .........;
BANK_INFO info = new BANK_INFO();
info.opencallback = LoadedBank.OpenBankStreamCallback;
info.closecallback = LoadedBank.CloseBankStreamCallback;
info.seekcallback = LoadedBank.SeekBankStreamCallback;
info.readcallback = LoadedBank.ReadBankStreamCallback;
StreamToIntPtr(fmodStream, out info.userdata);
info.userdatalength = Marshal.SizeOf(info.userdata);
loadResult = StudioSystem.loadBankCustom(info, loadBankFlags, out bank);
#region
[MonoPInvokeCallback(typeof(FMOD.FILE_OPEN_CALLBACK))]
public static RESULT OpenBankStreamCallback(StringWrapper name, ref uint filesize, ref IntPtr handle, IntPtr userdata)
{
handle = userdata;
Stream stream = null;
IntPtrToStream(handle, out stream);
filesize = (uint)stream.Length;
return RESULT.OK;
}
[MonoPInvokeCallback(typeof(FMOD.FILE_CLOSE_CALLBACK))]
public static RESULT CloseBankStreamCallback(IntPtr handle, IntPtr userdata)
{
Stream stream = null;
IntPtrToStream(handle, out stream);
stream.Close();
return RESULT.OK;
}
[MonoPInvokeCallback(typeof(FMOD.FILE_SEEK_CALLBACK))]
public static RESULT SeekBankStreamCallback(IntPtr handle, uint pos, IntPtr userdata)
{
RESULT result = RESULT.ERR_FILE_NOTFOUND;
Stream stream = null;
IntPtrToStream(handle, out stream);
var resPos = stream.Seek((long)pos, 0);
if (resPos != -1)
result = RESULT.OK;
return result;
}
[MonoPInvokeCallback(typeof(FMOD.FILE_READ_CALLBACK))]
public static RESULT ReadBankStreamCallback(IntPtr handle, IntPtr buffer, uint sizebytes, ref uint bytesread, IntPtr userdata)
{
RESULT result = RESULT.ERR_FILE_NOTFOUND;
Stream stream = null;
IntPtrToStream(handle, out stream);
byte[] readBuffer = new byte[(int)sizebytes];
uint bytesRead = (uint)stream.Read(readBuffer, 1, (int)sizebytes);
buffer = ArrToPtr(readBuffer);
bytesread = bytesRead;
if (bytesRead != sizebytes)
{
result = RESULT.ERR_FILE_EOF;
}
else if (bytesRead > 0)
{
result = RESULT.OK;
}
return result;
}
#endregion