diff --git a/CUETools.Codecs.WMA/CUETools.Codecs.WMA.csproj b/CUETools.Codecs.WMA/CUETools.Codecs.WMA.csproj
index 134c493..3ee6bbb 100644
--- a/CUETools.Codecs.WMA/CUETools.Codecs.WMA.csproj
+++ b/CUETools.Codecs.WMA/CUETools.Codecs.WMA.csproj
@@ -59,6 +59,7 @@
+
diff --git a/CUETools.Codecs.WMA/IStreamWrapper.cs b/CUETools.Codecs.WMA/IStreamWrapper.cs
new file mode 100644
index 0000000..c38c770
--- /dev/null
+++ b/CUETools.Codecs.WMA/IStreamWrapper.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices.ComTypes;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace CUETools.Codecs.WMA
+{
+ public class StreamWrapper : IStream
+ {
+ public StreamWrapper(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException("stream", "Can't wrap null stream.");
+ this.stream = stream;
+ }
+
+ private Stream stream;
+
+ public void Read(byte[] pv, int cb, System.IntPtr pcbRead)
+ {
+ Marshal.WriteInt32(pcbRead, (Int32)stream.Read(pv, 0, cb));
+ }
+
+ public void Seek(long dlibMove, int dwOrigin, System.IntPtr plibNewPosition)
+ {
+ var res = stream.Seek(dlibMove, (SeekOrigin)dwOrigin);
+ if (plibNewPosition != IntPtr.Zero) Marshal.WriteInt32(plibNewPosition, (int)res);
+ }
+
+ public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
+ {
+ if (grfStatFlag != 1) // STATFLAG_NONAME
+ throw new NotSupportedException();
+ var statstg = new System.Runtime.InteropServices.ComTypes.STATSTG();
+ statstg.type = 2; // STGTY.STREAM
+ statstg.cbSize = stream.Length;
+ pstatstg = statstg;
+ }
+
+ public void Clone(out IStream ppstm)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Commit(int grfCommitFlags)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void LockRegion(long libOffset, long cb, int dwLockType)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Revert()
+ {
+ throw new NotSupportedException();
+ }
+
+ public void SetSize(long libNewSize)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void UnlockRegion(long libOffset, long cb, int dwLockType)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Write(byte[] pv, int cb, IntPtr pcbWritten)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/CUETools.Codecs.WMA/WMAReader.cs b/CUETools.Codecs.WMA/WMAReader.cs
index c7d6be9..a1eb461 100644
--- a/CUETools.Codecs.WMA/WMAReader.cs
+++ b/CUETools.Codecs.WMA/WMAReader.cs
@@ -40,11 +40,13 @@ namespace CUETools.Codecs.WMA
long m_sampleCount = -1, m_sampleOffset = 0;
- string _path;
- //Stream _IO;
+ string m_path;
+ Stream m_IO;
+ StreamWrapper m_streamWrapper;
public WMAReader(string path, Stream IO)
{
+ m_path = path;
isValid(path);
bool pfIsProtected;
WMUtils.WMIsContentProtected(path, out pfIsProtected);
@@ -52,8 +54,16 @@ namespace CUETools.Codecs.WMA
throw new Exception("DRM present");
WMUtils.WMCreateSyncReader(IntPtr.Zero, Rights.None, out m_syncReader);
- //m_syncReader.OpenStream()
- m_syncReader.Open(path);
+ if (path == null)
+ {
+ m_IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000);
+ m_streamWrapper = new StreamWrapper(m_IO);
+ m_syncReader.OpenStream(m_streamWrapper);
+ }
+ else
+ {
+ m_syncReader.Open(path);
+ }
var pProfile = (m_syncReader as IWMProfile);
int dwStreamCount;
pProfile.GetStreamCount(out dwStreamCount);
@@ -193,7 +203,6 @@ namespace CUETools.Codecs.WMA
//}
pcm = new AudioPCMConfig(m_pWfx.wBitsPerSample, m_pWfx.nChannels, m_pWfx.nSamplesPerSec);
- _path = path;
//int cbMax;
//m_syncReader.GetMaxOutputSampleSize(m_dwAudioOutputNum, out cbMax);
@@ -214,7 +223,10 @@ namespace CUETools.Codecs.WMA
public void Close()
{
- //_IO.Close();
+ //if (m_streamWrapper != null)
+ // m_streamWrapper.Close();
+ if (m_IO != null)
+ m_IO.Close();
if (m_pSample != null)
Marshal.ReleaseComObject(m_pSample);
if (m_syncReader != null)
@@ -222,6 +234,7 @@ namespace CUETools.Codecs.WMA
m_syncReader.Close();
Marshal.ReleaseComObject(m_syncReader);
}
+ m_IO = null;
m_pSample = null;
m_syncReader = null;
}
@@ -252,48 +265,13 @@ namespace CUETools.Codecs.WMA
{
if (m_sampleCount < 0 || value > m_sampleCount)
throw new Exception("seeking past end of stream");
- throw new NotSupportedException();
- //if (value < Position || value > _sampleOffset)
- //{
- // if (seek_table != null && _IO.CanSeek)
- // {
- // int best_st = -1;
- // for (int st = 0; st < seek_table.Length; st++)
- // {
- // if (seek_table[st].number <= value &&
- // (best_st == -1 || seek_table[st].number > seek_table[best_st].number))
- // best_st = st;
- // }
- // if (best_st != -1)
- // {
- // _framesBufferLength = 0;
- // _samplesInBuffer = 0;
- // _samplesBufferOffset = 0;
- // _IO.Position = (long)seek_table[best_st].offset + first_frame_offset;
- // _sampleOffset = seek_table[best_st].number;
- // }
- // }
- // if (value < Position)
- // throw new Exception("cannot seek backwards without seek table");
- //}
- //while (value > _sampleOffset)
- //{
- // _samplesInBuffer = 0;
- // _samplesBufferOffset = 0;
-
- // fill_frames_buffer();
- // if (_framesBufferLength == 0)
- // throw new Exception("seek failed");
-
- // int bytesDecoded = DecodeFrame(_framesBuffer, _framesBufferOffset, _framesBufferLength);
- // _framesBufferLength -= bytesDecoded;
- // _framesBufferOffset += bytesDecoded;
-
- // _sampleOffset += _samplesInBuffer;
- //};
- //int diff = _samplesInBuffer - (int)(_sampleOffset - value);
- //_samplesInBuffer -= diff;
- //_samplesBufferOffset += diff;
+ if (value < Position)
+ throw new NotSupportedException();
+ if (value < Position)
+ throw new Exception("cannot seek backwards");
+ var buff = new AudioBuffer(this, 0x10000);
+ while (value > Position && Read(buff, (int)Math.Min(Int32.MaxValue, value - Position)) != 0)
+ ;
}
}
@@ -309,7 +287,7 @@ namespace CUETools.Codecs.WMA
{
get
{
- return _path;
+ return m_path;
}
}