mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
WavPack can also be read from RAR archive
This commit is contained in:
@@ -177,6 +177,7 @@ namespace APETagsDotNet
|
|||||||
{
|
{
|
||||||
m_spIO = new FileStream(filename, FileMode.Open, isReadonly?FileAccess.Read:FileAccess.ReadWrite, FileShare.Read);
|
m_spIO = new FileStream(filename, FileMode.Open, isReadonly?FileAccess.Read:FileAccess.ReadWrite, FileShare.Read);
|
||||||
m_spInfo = new FileInfo(filename);
|
m_spInfo = new FileInfo(filename);
|
||||||
|
_closeIO = true;
|
||||||
m_lastModified = m_spInfo.LastWriteTime;
|
m_lastModified = m_spInfo.LastWriteTime;
|
||||||
m_bAnalyzed = false;
|
m_bAnalyzed = false;
|
||||||
m_aryFields = new APETagField[0];
|
m_aryFields = new APETagField[0];
|
||||||
@@ -185,9 +186,27 @@ namespace APETagsDotNet
|
|||||||
if (analyze) Analyze ();
|
if (analyze) Analyze ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create an APE tags object
|
||||||
|
// bAnalyze determines whether it will analyze immediately or on the first request
|
||||||
|
// be careful with multiple threads / file pointer movement if you don't analyze immediately
|
||||||
|
public APETagDotNet(Stream IO, bool analyze)
|
||||||
|
{
|
||||||
|
m_spIO = IO;
|
||||||
|
_closeIO = false;
|
||||||
|
m_bAnalyzed = false;
|
||||||
|
m_aryFields = new APETagField[0];
|
||||||
|
m_nTagBytes = 0;
|
||||||
|
m_bIgnoreReadOnly = false;
|
||||||
|
if (analyze) Analyze();
|
||||||
|
}
|
||||||
|
|
||||||
public void Close ()
|
public void Close ()
|
||||||
{
|
{
|
||||||
m_spIO.Close ();
|
if (_closeIO)
|
||||||
|
{
|
||||||
|
m_spIO.Close();
|
||||||
|
m_spIO = null;
|
||||||
|
}
|
||||||
ClearFields ();
|
ClearFields ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,7 +648,7 @@ namespace APETagsDotNet
|
|||||||
//int GetFieldID3String(string pFieldName, char * pBuffer, int nBytes);
|
//int GetFieldID3String(string pFieldName, char * pBuffer, int nBytes);
|
||||||
|
|
||||||
// private data
|
// private data
|
||||||
private FileStream m_spIO;
|
private Stream m_spIO;
|
||||||
private FileInfo m_spInfo;
|
private FileInfo m_spInfo;
|
||||||
private DateTime m_lastModified;
|
private DateTime m_lastModified;
|
||||||
private bool m_bAnalyzed;
|
private bool m_bAnalyzed;
|
||||||
@@ -639,5 +658,6 @@ namespace APETagsDotNet
|
|||||||
private int m_nAPETagVersion;
|
private int m_nAPETagVersion;
|
||||||
//private bool m_bHasID3Tag;
|
//private bool m_bHasID3Tag;
|
||||||
private bool m_bIgnoreReadOnly;
|
private bool m_bIgnoreReadOnly;
|
||||||
|
private bool _closeIO;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace CUEToolsLib {
|
|||||||
case ".flac":
|
case ".flac":
|
||||||
return new FLACReader(path, null);
|
return new FLACReader(path, null);
|
||||||
case ".wv":
|
case ".wv":
|
||||||
return new WavPackReader(path);
|
return new WavPackReader(path, null, null);
|
||||||
case ".ape":
|
case ".ape":
|
||||||
return new APEReader(path);
|
return new APEReader(path);
|
||||||
case ".m4a":
|
case ".m4a":
|
||||||
@@ -37,6 +37,8 @@ namespace CUEToolsLib {
|
|||||||
#if !MONO
|
#if !MONO
|
||||||
case ".flac":
|
case ".flac":
|
||||||
return new FLACReader(path, IO);
|
return new FLACReader(path, IO);
|
||||||
|
case ".wv":
|
||||||
|
return new WavPackReader(path, IO, null);
|
||||||
case ".m4a":
|
case ".m4a":
|
||||||
return new ALACReader(path, IO);
|
return new ALACReader(path, IO);
|
||||||
#endif
|
#endif
|
||||||
@@ -416,8 +418,8 @@ namespace CUEToolsLib {
|
|||||||
class WavPackReader : IAudioSource {
|
class WavPackReader : IAudioSource {
|
||||||
WavPackDotNet.WavPackReader _wavPackReader;
|
WavPackDotNet.WavPackReader _wavPackReader;
|
||||||
|
|
||||||
public WavPackReader(string path) {
|
public WavPackReader(string path, Stream IO, Stream IO_WVC) {
|
||||||
_wavPackReader = new WavPackDotNet.WavPackReader(path);
|
_wavPackReader = new WavPackDotNet.WavPackReader(path, IO, IO_WVC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close() {
|
public void Close() {
|
||||||
|
|||||||
@@ -88,10 +88,7 @@ namespace FLACDotNet {
|
|||||||
_sampleBuffer = nullptr;
|
_sampleBuffer = nullptr;
|
||||||
_path = path;
|
_path = path;
|
||||||
|
|
||||||
if (IO)
|
_IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read);
|
||||||
_IO = IO;
|
|
||||||
else
|
|
||||||
_IO = gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read);
|
|
||||||
|
|
||||||
_decoder = FLAC__stream_decoder_new();
|
_decoder = FLAC__stream_decoder_new();
|
||||||
|
|
||||||
|
|||||||
@@ -13,18 +13,20 @@ namespace UnRarDotNet
|
|||||||
{
|
{
|
||||||
public class RarStream : Stream
|
public class RarStream : Stream
|
||||||
{
|
{
|
||||||
public RarStream(string archive, string fileName)
|
public RarStream(string path, string fileName)
|
||||||
{
|
{
|
||||||
_stop = false;
|
_close = false;
|
||||||
|
_eof = false;
|
||||||
|
_rewind = false;
|
||||||
_unrar = new Unrar();
|
_unrar = new Unrar();
|
||||||
_buffer = null;
|
_buffer = null;
|
||||||
_offset = 0;
|
_offset = 0;
|
||||||
_length = 0;
|
_length = 0;
|
||||||
_pos = 0;
|
_pos = 0;
|
||||||
|
_path = path;
|
||||||
|
_fileName = fileName;
|
||||||
_unrar.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired);
|
_unrar.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired);
|
||||||
_unrar.DataAvailable += new DataAvailableHandler(unrar_DataAvailable);
|
_unrar.DataAvailable += new DataAvailableHandler(unrar_DataAvailable);
|
||||||
_unrar.Open(archive, Unrar.OpenMode.Extract);
|
|
||||||
_fileName = fileName;
|
|
||||||
_workThread = new Thread(Decompress);
|
_workThread = new Thread(Decompress);
|
||||||
_workThread.Priority = ThreadPriority.BelowNormal;
|
_workThread.Priority = ThreadPriority.BelowNormal;
|
||||||
_workThread.IsBackground = true;
|
_workThread.IsBackground = true;
|
||||||
@@ -48,7 +50,7 @@ namespace UnRarDotNet
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
while (_size == null && !_stop)
|
while (_size == null && !_close)
|
||||||
Monitor.Wait(this);
|
Monitor.Wait(this);
|
||||||
}
|
}
|
||||||
if (_size == null)
|
if (_size == null)
|
||||||
@@ -65,7 +67,7 @@ namespace UnRarDotNet
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
_stop = true;
|
_close = true;
|
||||||
Monitor.Pulse(this);
|
Monitor.Pulse(this);
|
||||||
}
|
}
|
||||||
if (_workThread != null)
|
if (_workThread != null)
|
||||||
@@ -95,7 +97,7 @@ namespace UnRarDotNet
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
while (_buffer == null && !_stop)
|
while (_buffer == null && !_eof)
|
||||||
Monitor.Wait(this);
|
Monitor.Wait(this);
|
||||||
if (_buffer == null)
|
if (_buffer == null)
|
||||||
return total;
|
return total;
|
||||||
@@ -139,7 +141,7 @@ namespace UnRarDotNet
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
while (_size == null && !_stop)
|
while (_size == null && !_close)
|
||||||
Monitor.Wait(this);
|
Monitor.Wait(this);
|
||||||
if (_size == null)
|
if (_size == null)
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
@@ -163,8 +165,15 @@ namespace UnRarDotNet
|
|||||||
}
|
}
|
||||||
if (_seek_to.Value < _pos)
|
if (_seek_to.Value < _pos)
|
||||||
{
|
{
|
||||||
_seek_to = null;
|
lock (this)
|
||||||
throw new NotSupportedException("cannot seek backwards");
|
{
|
||||||
|
_pos = 0;
|
||||||
|
_rewind = true;
|
||||||
|
_buffer = null;
|
||||||
|
Monitor.Pulse(this);
|
||||||
|
}
|
||||||
|
//_seek_to = null;
|
||||||
|
//throw new NotSupportedException("cannot seek backwards");
|
||||||
}
|
}
|
||||||
return _seek_to.Value;
|
return _seek_to.Value;
|
||||||
}
|
}
|
||||||
@@ -176,12 +185,13 @@ namespace UnRarDotNet
|
|||||||
private Unrar _unrar;
|
private Unrar _unrar;
|
||||||
private string _fileName;
|
private string _fileName;
|
||||||
private Thread _workThread;
|
private Thread _workThread;
|
||||||
private bool _stop;
|
private bool _close, _rewind, _eof;
|
||||||
private byte[] _buffer;
|
private byte[] _buffer;
|
||||||
int _offset, _length;
|
int _offset, _length;
|
||||||
long? _size;
|
long? _size;
|
||||||
long? _seek_to;
|
long? _seek_to;
|
||||||
long _pos;
|
long _pos;
|
||||||
|
string _path;
|
||||||
|
|
||||||
private void unrar_PasswordRequired(object sender, PasswordRequiredEventArgs e)
|
private void unrar_PasswordRequired(object sender, PasswordRequiredEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -193,9 +203,15 @@ namespace UnRarDotNet
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
while (_buffer != null && !_stop)
|
while (_buffer != null && !_close)
|
||||||
Monitor.Wait(this);
|
Monitor.Wait(this);
|
||||||
if (_stop)
|
if (_close)
|
||||||
|
{
|
||||||
|
e.ContinueOperation = false;
|
||||||
|
Monitor.Pulse(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_rewind)
|
||||||
{
|
{
|
||||||
e.ContinueOperation = false;
|
e.ContinueOperation = false;
|
||||||
Monitor.Pulse(this);
|
Monitor.Pulse(this);
|
||||||
@@ -213,28 +229,47 @@ namespace UnRarDotNet
|
|||||||
{
|
{
|
||||||
//try
|
//try
|
||||||
{
|
{
|
||||||
while (_unrar.ReadHeader())
|
do
|
||||||
{
|
{
|
||||||
if (_unrar.CurrentFile.FileName == _fileName)
|
_unrar.Open(_path, Unrar.OpenMode.Extract);
|
||||||
|
while (_unrar.ReadHeader())
|
||||||
{
|
{
|
||||||
lock (this)
|
if (_unrar.CurrentFile.FileName == _fileName)
|
||||||
{
|
{
|
||||||
_size = _unrar.CurrentFile.UnpackedSize;
|
lock (this)
|
||||||
Monitor.Pulse(this);
|
{
|
||||||
|
if (_size == null)
|
||||||
|
{
|
||||||
|
_size = _unrar.CurrentFile.UnpackedSize;
|
||||||
|
Monitor.Pulse(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_unrar.Test();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
_unrar.Test();
|
else
|
||||||
break;
|
_unrar.Skip();
|
||||||
}
|
}
|
||||||
else
|
_unrar.Close();
|
||||||
_unrar.Skip();
|
lock (this)
|
||||||
}
|
{
|
||||||
|
_eof = true;
|
||||||
|
Monitor.Pulse(this);
|
||||||
|
while (!_rewind && !_close)
|
||||||
|
Monitor.Wait(this);
|
||||||
|
if (_close)
|
||||||
|
break;
|
||||||
|
_rewind = false;
|
||||||
|
_eof = false;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
//catch (StopExtractionException)
|
//catch (StopExtractionException)
|
||||||
//{
|
//{
|
||||||
//}
|
//}
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
_stop = true;
|
_close = true;
|
||||||
Monitor.Pulse(this);
|
Monitor.Pulse(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ using namespace System;
|
|||||||
using namespace System::Runtime::InteropServices;
|
using namespace System::Runtime::InteropServices;
|
||||||
using namespace System::Collections::Specialized;
|
using namespace System::Collections::Specialized;
|
||||||
using namespace System::Security::Cryptography;
|
using namespace System::Security::Cryptography;
|
||||||
|
using namespace System::IO;
|
||||||
using namespace APETagsDotNet;
|
using namespace APETagsDotNet;
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -43,21 +44,60 @@ using namespace APETagsDotNet;
|
|||||||
namespace WavPackDotNet {
|
namespace WavPackDotNet {
|
||||||
int write_block(void *id, void *data, int32_t length);
|
int write_block(void *id, void *data, int32_t length);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
||||||
|
public delegate int32_t DecoderReadDelegate(void *id, void *data, int32_t bcount);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
||||||
|
public delegate uint32_t DecoderTellDelegate(void *id);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
||||||
|
public delegate int DecoderSeekDelegate(void *id, uint32_t pos);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
||||||
|
public delegate int DecoderSeekRelativeDelegate(void *id, int32_t delta, int mode);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
||||||
|
public delegate int DecoderPushBackDelegate(void *id, int c);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
||||||
|
public delegate uint32_t DecoderLengthDelegate(void *id);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
||||||
|
public delegate int DecoderCanSeekDelegate(void *id);
|
||||||
|
|
||||||
public ref class WavPackReader {
|
public ref class WavPackReader {
|
||||||
public:
|
public:
|
||||||
WavPackReader(String^ path) {
|
WavPackReader(String^ path, Stream^ IO, Stream^ IO_WVC) {
|
||||||
IntPtr pathChars;
|
|
||||||
char errorMessage[256];
|
char errorMessage[256];
|
||||||
|
|
||||||
|
_readDel = gcnew DecoderReadDelegate (this, &WavPackReader::ReadCallback);
|
||||||
|
_tellDel = gcnew DecoderTellDelegate (this, &WavPackReader::TellCallback);
|
||||||
|
_seekDel = gcnew DecoderSeekDelegate (this, &WavPackReader::SeekCallback);
|
||||||
|
_seekRelDel = gcnew DecoderSeekRelativeDelegate (this, &WavPackReader::SeekRelCallback);
|
||||||
|
_pushBackDel = gcnew DecoderPushBackDelegate (this, &WavPackReader::PushBackCallback);
|
||||||
|
_lengthDel = gcnew DecoderLengthDelegate (this, &WavPackReader::LengthCallback);
|
||||||
|
_canSeekDel = gcnew DecoderCanSeekDelegate (this, &WavPackReader::CanSeekCallback);
|
||||||
|
|
||||||
|
ioReader = new WavpackStreamReader;
|
||||||
|
ioReader->read_bytes = (int32_t (*)(void *, void *, int32_t)) Marshal::GetFunctionPointerForDelegate(_readDel).ToPointer();
|
||||||
|
ioReader->get_pos = (uint32_t (*)(void *)) Marshal::GetFunctionPointerForDelegate(_tellDel).ToPointer();
|
||||||
|
ioReader->set_pos_abs = (int (*)(void *, uint32_t)) Marshal::GetFunctionPointerForDelegate(_seekDel).ToPointer();
|
||||||
|
ioReader->set_pos_rel = (int (*)(void *, int32_t, int)) Marshal::GetFunctionPointerForDelegate(_seekRelDel).ToPointer();
|
||||||
|
ioReader->push_back_byte = (int (*)(void *, int)) Marshal::GetFunctionPointerForDelegate(_pushBackDel).ToPointer();
|
||||||
|
ioReader->get_length = (uint32_t (*)(void *)) Marshal::GetFunctionPointerForDelegate(_lengthDel).ToPointer();
|
||||||
|
ioReader->can_seek = (int (*)(void *)) Marshal::GetFunctionPointerForDelegate(_canSeekDel).ToPointer();
|
||||||
|
ioReader->write_bytes = NULL;
|
||||||
|
|
||||||
|
_IO_ungetc = _IO_WVC_ungetc = -1;
|
||||||
|
|
||||||
_path = path;
|
_path = path;
|
||||||
|
|
||||||
pathChars = Marshal::StringToHGlobalUni(path);
|
_IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read);
|
||||||
size_t pathLen = wcslen ((const wchar_t*)pathChars.ToPointer())+1;
|
_IO_WVC = (IO != nullptr) ? IO_WVC : System::IO::File::Exists (path+"c") ? gcnew FileStream (path+"c", FileMode::Open, FileAccess::Read, FileShare::Read) : nullptr;
|
||||||
wchar_t * pPath = new wchar_t[pathLen];
|
|
||||||
memcpy ((void*) pPath, (const wchar_t*)pathChars.ToPointer(), pathLen*sizeof(wchar_t));
|
|
||||||
Marshal::FreeHGlobal(pathChars);
|
|
||||||
|
|
||||||
_wpc = WavpackOpenFileInput (pPath, errorMessage, OPEN_WVC, 0);
|
//IntPtr pathChars;
|
||||||
|
//pathChars = Marshal::StringToHGlobalUni(path);
|
||||||
|
//size_t pathLen = wcslen ((const wchar_t*)pathChars.ToPointer())+1;
|
||||||
|
//wchar_t * pPath = new wchar_t[pathLen];
|
||||||
|
//memcpy ((void*) pPath, (const wchar_t*)pathChars.ToPointer(), pathLen*sizeof(wchar_t));
|
||||||
|
//Marshal::FreeHGlobal(pathChars);
|
||||||
|
//_wpc = WavpackOpenFileInput (pPath, errorMessage, OPEN_WVC, 0);
|
||||||
|
|
||||||
|
_wpc = WavpackOpenFileInputEx (ioReader, "v", _IO_WVC != nullptr ? "c" : NULL, errorMessage, OPEN_WVC, 0);
|
||||||
if (_wpc == NULL) {
|
if (_wpc == NULL) {
|
||||||
throw gcnew Exception("Unable to initialize the decoder.");
|
throw gcnew Exception("Unable to initialize the decoder.");
|
||||||
}
|
}
|
||||||
@@ -71,6 +111,7 @@ namespace WavPackDotNet {
|
|||||||
|
|
||||||
~WavPackReader()
|
~WavPackReader()
|
||||||
{
|
{
|
||||||
|
delete ioReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
property Int32 BitsPerSample {
|
property Int32 BitsPerSample {
|
||||||
@@ -125,7 +166,7 @@ namespace WavPackDotNet {
|
|||||||
NameValueCollection^ get () {
|
NameValueCollection^ get () {
|
||||||
if (!_tags)
|
if (!_tags)
|
||||||
{
|
{
|
||||||
APETagDotNet^ apeTag = gcnew APETagDotNet (_path, true, true);
|
APETagDotNet^ apeTag = gcnew APETagDotNet (_IO, true);
|
||||||
_tags = apeTag->GetStringTags (true);
|
_tags = apeTag->GetStringTags (true);
|
||||||
apeTag->Close ();
|
apeTag->Close ();
|
||||||
}
|
}
|
||||||
@@ -136,8 +177,19 @@ namespace WavPackDotNet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() {
|
void Close()
|
||||||
|
{
|
||||||
_wpc = WavpackCloseFile(_wpc);
|
_wpc = WavpackCloseFile(_wpc);
|
||||||
|
if (_IO != nullptr)
|
||||||
|
{
|
||||||
|
_IO->Close ();
|
||||||
|
_IO = nullptr;
|
||||||
|
}
|
||||||
|
if (_IO_WVC != nullptr)
|
||||||
|
{
|
||||||
|
_IO_WVC->Close ();
|
||||||
|
_IO_WVC = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read(array<Int32, 2>^ sampleBuffer, Int32 sampleCount) {
|
void Read(array<Int32, 2>^ sampleBuffer, Int32 sampleCount) {
|
||||||
@@ -158,6 +210,106 @@ namespace WavPackDotNet {
|
|||||||
Int32 _sampleCount, _sampleOffset;
|
Int32 _sampleCount, _sampleOffset;
|
||||||
Int32 _bitsPerSample, _channelCount, _sampleRate;
|
Int32 _bitsPerSample, _channelCount, _sampleRate;
|
||||||
String^ _path;
|
String^ _path;
|
||||||
|
Stream^ _IO;
|
||||||
|
Stream^ _IO_WVC;
|
||||||
|
DecoderReadDelegate^ _readDel;
|
||||||
|
DecoderTellDelegate^ _tellDel;
|
||||||
|
DecoderSeekDelegate^ _seekDel;
|
||||||
|
DecoderSeekRelativeDelegate^ _seekRelDel;
|
||||||
|
DecoderPushBackDelegate^ _pushBackDel;
|
||||||
|
DecoderLengthDelegate^ _lengthDel;
|
||||||
|
DecoderCanSeekDelegate^ _canSeekDel;
|
||||||
|
array<unsigned char>^ _readBuffer;
|
||||||
|
int _IO_ungetc, _IO_WVC_ungetc;
|
||||||
|
WavpackStreamReader* ioReader;
|
||||||
|
|
||||||
|
int32_t ReadCallback (void *id, void *data, int32_t bcount)
|
||||||
|
{
|
||||||
|
Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO;
|
||||||
|
int IO_ungetc = (*(char*)id=='c') ? _IO_WVC_ungetc : _IO_ungetc;
|
||||||
|
int unget_len = 0;
|
||||||
|
|
||||||
|
if (IO_ungetc != -1)
|
||||||
|
{
|
||||||
|
*(unsigned char*)data = (unsigned char) IO_ungetc;
|
||||||
|
if (IO == _IO)
|
||||||
|
_IO_ungetc = -1;
|
||||||
|
else
|
||||||
|
_IO_WVC_ungetc = -1;
|
||||||
|
bcount --;
|
||||||
|
if (!bcount)
|
||||||
|
return 1;
|
||||||
|
data = 1 + (unsigned char*)data;
|
||||||
|
unget_len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_readBuffer == nullptr || _readBuffer->Length < bcount)
|
||||||
|
_readBuffer = gcnew array<unsigned char>(bcount < 0x4000 ? 0x4000 : bcount);
|
||||||
|
int len = IO->Read (_readBuffer, 0, bcount);
|
||||||
|
if (len) Marshal::Copy (_readBuffer, 0, (IntPtr)data, len);
|
||||||
|
return len + unget_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TellCallback(void *id)
|
||||||
|
{
|
||||||
|
Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO;
|
||||||
|
return IO->Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SeekCallback (void *id, uint32_t pos)
|
||||||
|
{
|
||||||
|
Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO;
|
||||||
|
IO->Position = pos;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SeekRelCallback (void *id, int32_t delta, int mode)
|
||||||
|
{
|
||||||
|
Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO;
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
IO->Seek (delta, System::IO::SeekOrigin::Begin);
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
IO->Seek (delta, System::IO::SeekOrigin::End);
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
IO->Seek (delta, System::IO::SeekOrigin::Current);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PushBackCallback (void *id, int c)
|
||||||
|
{
|
||||||
|
Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO;
|
||||||
|
if (IO == _IO)
|
||||||
|
{
|
||||||
|
if (_IO_ungetc != -1)
|
||||||
|
throw gcnew Exception("Double PushBackCallback unsupported.");
|
||||||
|
_IO_ungetc = c;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (_IO_WVC_ungetc != -1)
|
||||||
|
throw gcnew Exception("Double PushBackCallback unsupported.");
|
||||||
|
_IO_WVC_ungetc = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t LengthCallback (void *id)
|
||||||
|
{
|
||||||
|
Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO;
|
||||||
|
return IO->Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CanSeekCallback(void *id)
|
||||||
|
{
|
||||||
|
Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO;
|
||||||
|
return IO->CanSeek;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public ref class WavPackWriter {
|
public ref class WavPackWriter {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
Version="8,00"
|
Version="8,00"
|
||||||
Name="libwavpack"
|
Name="libwavpack"
|
||||||
ProjectGUID="{5CCCB9CF-0384-458F-BA08-72B73866840F}"
|
ProjectGUID="{5CCCB9CF-0384-458F-BA08-72B73866840F}"
|
||||||
|
RootNamespace="libwavpack"
|
||||||
Keyword="Win32Proj"
|
Keyword="Win32Proj"
|
||||||
>
|
>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
@@ -41,7 +42,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_MMX"
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_MMX;NO_USE_FSTREAMS;NO_TAGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
@@ -103,7 +104,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_SSE2"
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_SSE2;NO_USE_FSTREAMS;NO_TAGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
@@ -167,7 +168,7 @@
|
|||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_MMX"
|
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_MMX;NO_USE_FSTREAMS;NO_TAGS"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
ExceptionHandling="0"
|
ExceptionHandling="0"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
@@ -239,7 +240,7 @@
|
|||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_SSE2"
|
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_SSE2;NO_USE_FSTREAMS;NO_TAGS"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
ExceptionHandling="0"
|
ExceptionHandling="0"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
|
|||||||
Reference in New Issue
Block a user