[Matroska-cvs] [matroska] r1250 - trunk/foo_matroska

ayana at matroska.org ayana at matroska.org
Sun Apr 30 14:46:27 CEST 2006


Author: ayana
Date: 2006-04-30 16:46:18 +0400 (Sun, 30 Apr 2006)
New Revision: 1250

Added:
   trunk/foo_matroska/foo_input_matroska.rc
   trunk/foo_matroska/foo_input_matroska.vcproj
Removed:
   trunk/foo_matroska/foo_matroska.dsp
   trunk/foo_matroska/foo_matroska.rc
Modified:
   trunk/foo_matroska/DbgOut.h
   trunk/foo_matroska/Foobar2000ReaderIOCallback.h
   trunk/foo_matroska/foo_input_matroska.cpp
   trunk/foo_matroska/matroska_parser.cpp
   trunk/foo_matroska/matroska_parser.h
Log:
poted to foobar2000 0.9.x

Modified: trunk/foo_matroska/DbgOut.h
===================================================================
--- trunk/foo_matroska/DbgOut.h	2006-04-30 12:41:04 UTC (rev 1249)
+++ trunk/foo_matroska/DbgOut.h	2006-04-30 12:46:18 UTC (rev 1250)
@@ -24,6 +24,27 @@
 
 #ifdef _DEBUG
 //#define DEBUG_OUT_PUT
+#include <tchar.h>
+#include <stdarg.h>
+#define HPRINTF_MES_LENGTH 256
+inline void hprintf( const _TCHAR * format, ... )
+{
+    _TCHAR buff[HPRINTF_MES_LENGTH];
+    va_list vl;
+    va_start(vl, format);
+    _vsntprintf(buff, HPRINTF_MES_LENGTH, format, vl);
+    va_end(vl);
+    OutputDebugString(buff);
+}
+#include <boost/timer.hpp>
+#define TIMER boost::timer t
+#define RETIMER t.restart()
+#define _TIMER(x) hprintf(L"%S: %f sec.\n",x,t.elapsed())
+#else
+#define TIMER __noop
+#define RETIMER __noop
+#define _TIMER(x) __noop
+#define hprintf __noop
 #endif
 
 #ifdef DEBUG_OUT_PUT

Modified: trunk/foo_matroska/Foobar2000ReaderIOCallback.h
===================================================================
--- trunk/foo_matroska/Foobar2000ReaderIOCallback.h	2006-04-30 12:41:04 UTC (rev 1249)
+++ trunk/foo_matroska/Foobar2000ReaderIOCallback.h	2006-04-30 12:46:18 UTC (rev 1250)
@@ -23,13 +23,16 @@
 
 class Foobar2000ReaderIOCallback : public IOCallback {
 public:
-	Foobar2000ReaderIOCallback(reader *source) {
+	Foobar2000ReaderIOCallback(service_ptr_t<file> source, abort_callback & p_abort)
+		: m_abort(p_abort)
+	{
 		m_NoSeekReader = NULL;
 		m_Reader = source;
-		m_Reader->service_add_ref();
+		m_abort = p_abort;
+		//m_Reader->service_add_ref();
 		if (!m_Reader->can_seek()) {
 			m_NoSeekReader = source;
-			m_Reader = new service_impl_p2_t<reader_seekback_wrap,reader*,unsigned>(source, 1024*1024);
+			//m_Reader = new service_impl_p2_t<reader_seekback_wrap,service_ptr_t<file>,unsigned>(source, 1024*1024);
 		}
 	};
 	virtual ~Foobar2000ReaderIOCallback() {
@@ -37,20 +40,20 @@
 	};
 
 	virtual uint32 read(void*Buffer, size_t Size) {
-		return m_Reader->read(Buffer, Size);
+		return m_Reader->read(Buffer, Size, m_abort);
 	};
 
 	virtual void setFilePointer(int64 Offset, seek_mode Mode=seek_beginning) {
 		switch (Mode)
 		{
 			case seek_beginning:
-				m_Reader->seek(Offset);
+				m_Reader->seek(Offset, m_abort);
 				break;
 			case seek_current:
-				m_Reader->seek2(Offset, SEEK_CUR);
+				m_Reader->seek_ex(Offset, file::t_seek_mode::seek_from_current, m_abort);
 				break;
 			case seek_end:
-				m_Reader->seek2(Offset, SEEK_END);
+				m_Reader->seek_ex(Offset, file::t_seek_mode::seek_from_eof, m_abort);
 				break;
 			default:
 				//throw "Invalid Seek Mode!!!";
@@ -59,20 +62,21 @@
 	}
 
 	virtual size_t write(const void*Buffer, size_t Size) {
-		return m_Reader->write(Buffer, Size);
+		m_Reader->write(Buffer, Size, m_abort);
+		return Size;
 	}
 
 	virtual uint64 getFilePointer() {
-		return m_Reader->get_position();
+		return m_Reader->get_position(m_abort);
 	};
 
 	virtual void close() {
 		if (m_Reader != NULL) {
-			m_Reader->service_release();
+			//m_Reader->service_release();
 			m_Reader = NULL;
 		}
 		if (m_NoSeekReader != NULL) {
-			m_NoSeekReader->service_release();
+			//m_NoSeekReader->service_release();
 			m_NoSeekReader = NULL;
 		}
 	}
@@ -85,12 +89,14 @@
 
 	bool truncate()
 	{
-		return m_Reader->set_eof();
+		m_Reader->set_eof(m_abort);
+		return true;
 	}
 
 protected:
-	reader *m_Reader;
-	reader *m_NoSeekReader;
+	service_ptr_t<file> m_Reader;
+	service_ptr_t<file> m_NoSeekReader;
+	abort_callback & m_abort;
 };
 
 #endif // _FOOBAR2000_IO_CALLBACK_H_

Modified: trunk/foo_matroska/foo_input_matroska.cpp
===================================================================
--- trunk/foo_matroska/foo_input_matroska.cpp	2006-04-30 12:41:04 UTC (rev 1249)
+++ trunk/foo_matroska/foo_input_matroska.cpp	2006-04-30 12:46:18 UTC (rev 1250)
@@ -56,25 +56,27 @@
 #include <commctrl.h>
 #include <Shlwapi.h>
 #include <time.h>
+#include "matroska_parser.h"
 #include "resource.h"
-#include "matroska_parser.h"
 #include "DbgOut.h"
 
-class input_matroska : public input
+class input_matroska
 {
 	MatroskaAudioParser *m_parser;
-	reader *m_matroskaFile;
-	packet_decoder *m_decoder;
+	service_ptr_t<packet_decoder> m_decoder;
+	t_input_open_reason m_reason;
 
 	int m_TrackNo;
+	int m_subsong;
 	// Compressed data frame
 	MatroskaAudioFrame * m_frame;
 	unsigned m_frame_remaining;
 
-	unsigned m_skip_samples;
-	unsigned m_skip_frames;
+	uint64 m_skip_samples;
+	uint64 m_skip_frames;
 	unsigned m_expected_sample_rate;
 	unsigned m_expected_channels;
+	unsigned m_expected_bitspersample;
 	uint64 m_timescale;
 	
 	// VBR bitrate display stuff
@@ -87,10 +89,15 @@
 
 	// A temp decoding buffer
 	audio_chunk_i m_tempchunk;
+
+public:
+	service_ptr_t<file> m_file;
+	pfc::array_t<t_uint8> m_buffer;
 	
 public:
 	input_matroska()
 	{
+		hprintf(L"Matroska: input_matroska()\n");
 		m_parser = NULL;
 		m_decoder = NULL;
 		m_TrackNo = 0;
@@ -113,16 +120,12 @@
 
 	~input_matroska()
 	{
+		hprintf(L"Matroska: ~input_matroska()\n");
 		cleanup();
 	}
 
-	virtual bool test_filename(const char * fn,const char * ext)
+	void open(service_ptr_t<file> p_filehint, const char * p_path, t_input_open_reason p_reason, abort_callback & p_abort)
 	{
-		return (!stricmp(ext,"MKA") || !stricmp(ext,"MKV"));
-	}
-
-	virtual bool open(reader *r, file_info *info, unsigned flags)
-	{
 		// TODO : Use the Cueing Data if we can seek
 
 		/*if (!r->can_seek())
@@ -130,121 +133,124 @@
 			console::error("Matroska: unseekable streams not supported.");
 			return false;
 		}*/
+		hprintf(L"Matroska: open() p_reason=%d\n", p_reason);
 
 		cleanup();
 
-		m_parser = new MatroskaAudioParser(r);
+		m_file = p_filehint;
+		input_open_file_helper(m_file, p_path, p_reason, p_abort);
+		m_reason = p_reason;
 
-		if (m_parser->Parse(!(flags & OPEN_FLAG_DECODE))) {
+		m_parser = new MatroskaAudioParser(m_file, p_abort);
+
+		if (m_parser->Parse(!(p_reason & input_open_decode))) {
 			console::error("Matroska: Invalid Matroska file.");
-			return false;			
-		}		
+			throw exception_io_unsupported_format();
+		}
 
 		m_TrackNo = m_parser->GetFirstAudioTrack();
 		if (m_TrackNo == -1) {
 			console::error("Matroska: no decodable streams found.");
-			return false;
-		}	
+			throw exception_io_unsupported_format();
+		}
+	}
 
-#ifdef MULTITRACK
+	unsigned int get_subsong_count() {
+		hprintf(L"Matroska: get_subsong_count() chapters=%d, AudioTrackCount=%d\n", m_parser->GetChapters().size(), m_parser->GetAudioTrackCount());
+		if (m_parser->GetChapters().size() > 0) {
+			return m_parser->GetChapters().size();
+		} else if(m_parser->GetAudioTrackCount() > 0) {
+			return m_parser->GetAudioTrackCount();
+		}
+		return 0;
+	}
+
+	t_uint32 get_subsong(unsigned p_index) {
+		hprintf(L"Matroska: get_subsong() chapters= %d, p_index=%d\n", m_parser->GetChapters().size(), p_index);
+		return p_index;
 		if(m_parser->GetChapters().size() > 0)
-		{			
-			int idx = info->get_subsong_index() / m_parser->GetChapters().size();
+		{
+			int tr = 0;
+			int idx = p_index / m_parser->GetChapters().size();
 			m_TrackNo = m_parser->GetAudioTrackIndex(idx);
+			m_subsong = p_index % m_parser->GetChapters().size();
 			m_parser->SetCurrentTrack(m_TrackNo);
-			m_parser->SetSubSong(info->get_subsong_index() % m_parser->GetChapters().size());
+			return p_index;
 		} else {
-			m_TrackNo = m_parser->GetAudioTrackIndex(info->get_subsong_index());
+			m_TrackNo = m_parser->GetAudioTrackIndex(p_index);
+			m_subsong = 0;
 			m_parser->SetCurrentTrack(m_TrackNo);
-			m_parser->SetSubSong(0);
+			return p_index;
 		}
-#else
-		m_parser->SetSubSong(info->get_subsong_index());
-		m_parser->SetCurrentTrack(m_TrackNo);
-#endif
-			
-		// Set the current track
+	}
 
-		MatroskaTrackInfo &currentTrack = m_parser->GetTrack(m_TrackNo);
-		m_expected_channels = currentTrack.channels;
-		m_expected_sample_rate = currentTrack.samplesOutputPerSec == 0 ? currentTrack.samplesPerSec : currentTrack.samplesOutputPerSec;
+	void get_info(t_uint32 p_subsong,file_info & p_info,abort_callback & p_abort) {
+		hprintf(L"Matroska: get_info() = %d\n", p_subsong);
+		if (m_reason != input_open_decode || m_decoder == NULL) {
+			set_current_track(p_subsong);
+			initialize_decorder(p_abort);
+		}
+		p_info.info_set_int("channels", m_expected_channels);
+		p_info.info_set_int("samplerate", m_expected_sample_rate);
 
-		info->info_set_int("channels", m_expected_channels);
-		info->info_set_int("samplerate", m_expected_sample_rate);
-//		info->info_set_int("bitspersample", currentTrack.bitsPerSample);
+		m_decoder->get_info(p_info);
+		
+		m_expected_channels = (unsigned)p_info.info_get_int("channels");
+		m_expected_sample_rate = (unsigned)p_info.info_get_int("samplerate");
+		m_expected_bitspersample = (unsigned)p_info.info_get_int("bitspersample");
+		
+		m_decoder->set_stream_property(packet_decoder::property_channels, m_expected_channels, 0, 0);
+		m_decoder->set_stream_property(packet_decoder::property_samplerate, m_expected_sample_rate, 0, 0);
+		m_decoder->set_stream_property(packet_decoder::property_bitspersample, m_expected_bitspersample, 0, 0);
 
-		{
-			packet_decoder::matroska_setup setup;
-			string8 codec_temp(currentTrack.codecID.c_str());
-			setup.codec_id = codec_temp;
-			setup.sample_rate = currentTrack.samplesPerSec;
-			setup.sample_rate_output = currentTrack.samplesOutputPerSec;
-			setup.channels = m_expected_channels;
-			setup.codec_private_size = currentTrack.codecPrivate.size();
-			setup.codec_private = &currentTrack.codecPrivate[0];
+		m_parser->SetFB2KInfo(p_info, m_subsong);
 
-			m_decoder = packet_decoder::g_open(packet_decoder::owner_matroska,0,&setup,sizeof(setup),info);
-			
-			if (m_decoder == NULL)
-			{
-				console::error(uStringPrintf("Matroska: unable to find a \"%s\" packet decoder object.", (const char*)codec_temp));
-				cleanup();
-				return false;
-			} else {
-				console::info(uStringPrintf("Matroska: using '%s' decoder.", (const char*)m_decoder->get_name()));
-			}
-		}
+		//hprintf(L"Matroska: m_parser->GetDuration(): %f\n", (double)(int64)m_parser->GetDuration() / 1000000000.0);
+		p_info.set_length((double)(int64)m_parser->GetDuration() / 1000000000.0);
 
-		m_expected_channels = info->info_get_int("channels");
-		m_expected_sample_rate = info->info_get_int("samplerate");
-		
-		m_decoder->set_stream_property(packet_decoder::property_channels,m_expected_channels,0,0,info);
-		m_decoder->set_stream_property(packet_decoder::property_samplerate,m_expected_sample_rate,0,0,info);
-		m_decoder->set_stream_property(packet_decoder::property_bitspersample,currentTrack.bitsPerSample,0,0,info);
+		p_info.info_set_bitrate(m_parser->GetAvgBitrate());
+	}
 
-		m_parser->SetFB2KInfo(info);
+	t_filestats get_file_stats(abort_callback & p_abort) {
+		hprintf(L"Matroska: get_file_stats()\n");
+		return m_file->get_stats(p_abort);
+	}
+
+	void decode_initialize(t_uint32 p_subsong, unsigned p_flags, abort_callback & p_abort) {
+		hprintf(L"Matroska: decode_initialize() = %d\n", p_subsong);
+		set_current_track(p_subsong);
+		initialize_decorder(p_abort);
+		m_decoder->reset_after_seek();
 		// The timecode scale in Matroska is in milliseconds, but foobar deals in seconds
-		m_timescale = m_parser->GetTimecodeScale() * 1000;		
-
+		m_timescale = m_parser->GetTimecodeScale() * 1000;
 		m_length = duration_to_samples(m_parser->GetDuration());
 		m_position = 0;
-
-		info->set_length((double)(int64)m_parser->GetDuration() / 1000000000.0);
-
-		info->info_set_bitrate(m_parser->GetAvgBitrate());
-		
-
-		if (flags & OPEN_FLAG_DECODE)
-		{
-			m_skip_samples = 0;
-			m_skip_frames = 0;
-			m_frame_remaining = 0;
-			m_frame = 0;
-
-			if (!seek(0)) return false;
-		}
-
-		return true;
+		m_skip_samples = 0;
+		m_skip_frames = 0;
+		m_frame_remaining = 0;
+		m_frame = 0;
+		decode_seek(0, p_abort);
 	}
 
-	virtual int run(audio_chunk * chunk)
-	{
+	bool decode_run(audio_chunk & p_chunk, abort_callback & p_abort) {
+		//hprintf(L"Matroska: decode_run(): m_skip_samples=%d, m_skip_frames=%d, m_frame_remaining=%d, m_frame=%p\n", (int)m_skip_samples, (int)m_skip_frames, m_frame_remaining, m_frame);
 		if (m_decoder == NULL)
 		{
-			console::error("Matroska: attempting to decode without a loaded decoder.");
-			return -1;
+			hprintf(L"Matroska: attempting to decode without a loaded decoder.\n");
+			return false;
 		}
 
 		if (m_position>=m_length)
 		{
-			return 0;
+			hprintf(L"Matroska: decode_run() return false\n");
+			return false;
 		}
-		
+
 		bool done = false;
 
 		do
 		{
-			unsigned char *buffer = NULL;
+			//unsigned char *buffer = NULL;
 			unsigned int buffer_size = 0;
 			bool skip_this_frame = false;
 /*
@@ -260,31 +266,38 @@
 					delete m_frame;
 				m_frame = m_parser->ReadSingleFrame();
 				if (m_frame==0)
-					return 0;
+					return false;
 				m_frame_remaining = m_frame->dataBuffer.size();
 				if (m_frame_remaining == 0)
-					return 0;
+					return false;
 			}
 
 			{
 				unsigned ptr = m_frame->dataBuffer.size() - (m_frame_remaining--);
-				buffer = (unsigned char*)&m_frame->dataBuffer.at(ptr)[0];
+				//buffer = (unsigned char*)&m_frame->dataBuffer.at(ptr)[0];
 				buffer_size = m_frame->dataBuffer.at(ptr).size();
+				m_buffer.set_size(buffer_size);
+				m_buffer.set_data_fromptr(&m_frame->dataBuffer.at(ptr)[0], buffer_size);
 			}
 			
 			m_tempchunk.reset();
-			if (!m_decoder->decode(buffer,buffer_size,&m_tempchunk))
+			m_decoder->decode(m_buffer.get_ptr(), buffer_size, m_tempchunk, p_abort);
+			if (m_tempchunk.is_empty())
 			{
-				console::error(uStringPrintf("Matroska: '%s' decode error.", (const char*)m_decoder->get_name()));
+				/*
+				MatroskaTrackInfo &currentTrack = m_parser->GetTrack(m_TrackNo);
+				console::error(uStringPrintf("Matroska: '%s' decode error.", (const char*)currentTrack.codecID.c_str()));
 				console::error(uStringPrintf("buffer_size = %d, m_frame_remaining = %d", buffer_size, m_frame_remaining));
-				console::error(uStringPrintf("buffer 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]));				
+				console::error(uStringPrintf("buffer 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", m_buffer[0], m_buffer[1], m_buffer[2], m_buffer[3], m_buffer[4], m_buffer[5], m_buffer[6], m_buffer[7]));				
 				cleanup();
-				return -1;
+				return false;
+				*/
 			}
-			else if (m_tempchunk.is_valid())
+			if (m_tempchunk.is_valid())
 			{
 				m_vbr_update_frames++;
 				m_vbr_update_bytes += buffer_size;
+				//m_vbr_update_bytes += m_buffer.get_size();
 				m_vbr_update_time += (m_vbr_last_duration = m_tempchunk.get_duration());
 			}
 
@@ -299,8 +312,8 @@
 
 			if (!skip_this_frame)
 			{				
-				unsigned offset = (unsigned)duration_to_samples(0);//m_frame.timecode);
-				unsigned duration = (unsigned)duration_to_samples(m_frame->duration);
+				uint64 offset = duration_to_samples(0);//m_frame.timecode);
+				uint64 duration = duration_to_samples(m_frame->duration);
 				//			console::info(uStringPrintf("duration: %u, offset: %u",duration,offset));
 
 				if (m_tempchunk.is_empty())
@@ -309,7 +322,7 @@
 					{
 						m_tempchunk.set_srate(m_expected_sample_rate);
 						m_tempchunk.set_channels(m_expected_channels);
-						m_tempchunk.pad_with_silence(duration);
+						m_tempchunk.pad_with_silence((t_size)duration);
 #ifdef _DEBUG
 						console::warning("Matroska: decoder returned empty chunk from a non-empty Matroska frame.");
 #endif
@@ -319,7 +332,7 @@
 				{
 					console::error("Matroska: decoder produced invalid chunk.");
 					cleanup();
-					return -1;
+					return false;
 				}
 				unsigned samplerate,channels,decoded_sample_count;
 
@@ -336,7 +349,7 @@
 #ifdef _DEBUG
 					console::warning("Matroska: decoded frame smaller than expected.");
 #endif
-					decoded_sample_count = duration;
+					decoded_sample_count = (unsigned)duration;
 					m_tempchunk.pad_with_silence(decoded_sample_count);
 				}
 
@@ -347,7 +360,7 @@
 
 				if (m_skip_samples>0)
 				{
-					unsigned int delta = (unsigned)m_skip_samples;
+					uint64 delta = m_skip_samples;
 					if (delta > duration) delta = duration;
 					offset += delta;
 					duration -= delta;
@@ -360,70 +373,48 @@
 						duration = max;
 					m_position += duration;
 					if (m_position==m_length && duration==0)
-						return 0;
+						return false;
 				}
 
 
 				if (duration > 0)
 				{
-					chunk->set_data_64(m_tempchunk.get_data() + offset * channels,
-						duration,channels,samplerate);
+					p_chunk.set_data(m_tempchunk.get_data() + offset * channels,
+						(t_size)duration,channels,samplerate);
+					//p_chunk.set_data_fixedpoint(m_tempchunk.get_data() + offset * channels, buffer_size, m_expected_sample_rate,m_expected_channels,m_expected_bitspersample,audio_chunk::g_guess_channel_config(m_expected_channels));
 					done = true;
 				}
 			}
 		}
 		while(!done);
 
-		return done ? 1 : 0;
+		return done;
 	}
 
-	virtual set_info_t set_info(reader *r, const file_info * info)
-	{
-		NOTE2("input_matroska::set_info(r = 0x%p, info = 0x%p)", r, info);
-		unsigned rv = 1;
+	void decode_seek(double p_seconds, abort_callback & p_abort) {
+		hprintf(L"Matroska: decode_seek() = %f\n", p_seconds);
 
-		// We have to create a new parser
-		MatroskaAudioParser writeReader(r);
-		writeReader.Parse(true);
-					
-		int TrackNo = writeReader.GetFirstAudioTrack();
-		if (TrackNo != -1) {				
-			// Set the current track
-			writeReader.SetCurrentTrack(m_TrackNo);
-			writeReader.SetSubSong(info->get_subsong_index());
-
-			rv = writeReader.WriteTags(info);			
-		}		
-
-		return !rv ? SET_INFO_SUCCESS : SET_INFO_FAILURE;
-	}
-
-	virtual bool seek(double seconds)
-	{
-		NOTE1("input_matroska::seek(seconds = %f)", seconds);
-
 		if (m_decoder == NULL)
 		{
 			console::error("Matroska: attempting to seek while not open.");
-			return false;
+			throw exception_io_object_not_seekable();
 		}
 
-		
 		{
 			double srate = (double)m_expected_sample_rate;
-			seconds = floor(seconds * srate + 0.5) / srate;
+			p_seconds = floor(p_seconds * srate + 0.5) / srate;
 		}
 
 		double max_frame_dependency_time = m_decoder->get_max_frame_dependency_time();
-		if (max_frame_dependency_time>seconds) max_frame_dependency_time = seconds;
+		if (max_frame_dependency_time>p_seconds) max_frame_dependency_time = p_seconds;
 		unsigned max_frame_dependency_samples = (unsigned)(m_expected_sample_rate * max_frame_dependency_time + 0.5);
 
 		unsigned frames_to_skip = 0;
 
-		m_position = (uint64)(m_expected_sample_rate * seconds + 0.5);
+		m_position = (uint64)(m_expected_sample_rate * p_seconds + 0.5);
 
 		double time_to_skip = 0;
-		if (!m_parser->Seek(seconds-max_frame_dependency_time,frames_to_skip,time_to_skip,m_expected_sample_rate)) return false;
+		if (!m_parser->Seek(p_seconds-max_frame_dependency_time,frames_to_skip,time_to_skip,m_expected_sample_rate)) throw exception_io_object_not_seekable();
 		
 		m_skip_frames = frames_to_skip;
 
@@ -431,51 +422,97 @@
 		m_frame_remaining = 0;
 		
 		//console::info(uStringPrintf("skip samples: %u",m_skip_samples));
-
-		return true;
 	}
 
-	virtual bool is_our_content_type(const char *url, const char *type)
-	{
-		NOTE2("input_matroska::is_our_content_type(url = %s, type = %s)", url, type);
-
-		return !stricmp(type, "audio/x-matroska") 
-			|| !stricmp(type, "video/x-matroska")
-			// Just to be safe check for ones without x-
-			// However, You're supposed to use x-* unless it's offically registered
-			|| !stricmp(type, "audio/matroska") 
-			|| !stricmp(type, "video/matroska");
+	bool decode_can_seek() {
+		hprintf(L"Matroska: decode_can_seek()\n");
+		return m_file->can_seek();
 	}
 
-	virtual bool get_dynamic_info(file_info * out,double * timestamp_delta,bool * b_track_change)
-	{
+	bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta) {
+		//hprintf(L"Matroska: decode_get_dynamic_info()\n");
 		bool ret = false;
 		if (m_vbr_update_enabled)
 		{
 			if (m_vbr_update_time > 0 && m_vbr_update_frames >= m_vbr_update_interval)
 			{
 				int val = (int) ( ((double)m_vbr_update_bytes * 8.0 / m_vbr_update_time + 500.0) / 1000.0 );
-				if (val != out->info_get_bitrate_vbr())
+				if (val != p_out.info_get_bitrate_vbr())
 				{
-					*timestamp_delta = - (m_vbr_update_time - m_vbr_last_duration);	//relative to last frame beginning;
-					out->info_set_bitrate_vbr(val);
+					p_timestamp_delta = - (m_vbr_update_time - m_vbr_last_duration);	//relative to last frame beginning;
+					p_out.info_set_bitrate_vbr(val);
 					ret = true;
 				}
 				m_vbr_update_frames = 0; m_vbr_update_bytes = 0;
 				m_vbr_update_time = 0;
 			}
-		}		
+		}
 		return ret;
 	}
 
+	bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta) {
+		//hprintf(L"Matroska: decode_get_dynamic_info_track()\n");
+		return false;
+	}
+
+	void decode_on_idle(abort_callback & p_abort) {
+		m_file->on_idle(p_abort);
+	}
+
+	void retag_set_info(t_uint32 p_subsong,const file_info & p_info,abort_callback & p_abort) {
+		hprintf(L"Matroska: retag_set_info()\n");
+		unsigned rv = 1;
+
+		if (m_parser == NULL) throw exception_io_unsupported_format();
+					
+		int TrackNo = m_parser->GetFirstAudioTrack();
+		if (TrackNo != -1) {
+			// Set the current track
+			m_parser->SetCurrentTrack(m_TrackNo);
+			m_parser->SetSubSong(p_subsong);
+			m_parser->SetTags(p_info);
+		}
+
+		//return !rv ? SET_INFO_SUCCESS : SET_INFO_FAILURE;
+	}
+
+	void retag_commit(abort_callback & p_abort) {
+		hprintf(L"Matroska: retag_commit()\n");
+		m_parser->WriteTags();
+	}
+
+	static bool g_is_our_content_type(const char * p_content_type) {
+		hprintf(L"Matroska: g_is_our_content_type() p_content_type=%S\n", p_content_type);
+		return !stricmp_utf8(p_content_type, "audio/x-matroska") 
+			|| !stricmp_utf8(p_content_type, "video/x-matroska")
+			// Just to be safe check for ones without x-
+			// However, You're supposed to use x-* unless it's offically registered
+			|| !stricmp_utf8(p_content_type, "audio/matroska") 
+			|| !stricmp_utf8(p_content_type, "video/matroska");
+	}
+
+	static bool g_is_our_path(const char * p_path,const char * p_extension) {
+		hprintf(L"Matroska: g_is_our_path() p_path=%S p_extension=%S\n", p_path, p_extension);
+		if (stricmp_utf8_partial(p_path, "http://", 7) == 0) {
+			// HTTP streams and chapters togther are not supported, requires seeking
+			return false;
+		} else {
+			if (stricmp_utf8(p_extension, "MKA") != 0 && stricmp_utf8(p_extension, "MKV") != 0)
+				return false;
+		}
+		return true;
+	}
+
 protected:
 	void cleanup()
 	{
-		if (m_decoder != NULL) 
+		/*
+		if (m_decoder != NULL)
 		{
-			m_decoder->service_release();
+			//m_decoder->service_release();
 			m_decoder = NULL;
 		}
+		*/
 		if (m_frame)
 		{
 			delete m_frame;
@@ -496,68 +533,59 @@
 		return (int64) ( (double)val * 1000000000.0 / (double)m_expected_sample_rate + 0.5);
 	}
 
-};
-
-static service_factory_t<input, input_matroska> foo_matroska;
-
-class track_indexer_matroska : public track_indexer
-{
-public:
-	virtual int get_tracks(const char* filename, callback * out, reader * r)
-	{
-		NOTE3("track_indexer_matroska::get_tracks(filename = %s, out = 0x%p, r = 0x%p", filename, out, r);
-		// Let's check the filename
-		if (!stricmp_utf8_partial(filename, "http://", 7)) {
-			// HTTP streams and chapters togther are not supported, requires seeking
-			return 0;
-		} else if (strlen(filename) > 3) {
-			const char *ext = filename+strlen(filename)-3;
-			if (!!stricmp(ext, "MKA") && !!stricmp(ext, "MKV"))
-				return 0;
+	void set_current_track(unsigned int p_index) {
+		if(m_parser->GetChapters().size() > 0)
+		{
+			int idx = p_index / m_parser->GetChapters().size();
+			m_TrackNo = m_parser->GetAudioTrackIndex(idx);
+			m_subsong = p_index % m_parser->GetChapters().size();
 		} else {
-			return 0;
+			m_TrackNo = m_parser->GetAudioTrackIndex(p_index);
+			m_subsong = 0;
 		}
-		if (r == NULL)
-			r = file::g_open_read(filename);
-		if (r == NULL) return 0;
-		
-		MatroskaAudioParser scanner(r);
-		scanner.Parse(true);
+		m_parser->SetCurrentTrack(m_TrackNo);
+		m_parser->SetSubSong(m_subsong);
+		hprintf(L"Matroska: set_current_track(): m_TrackNo=%d, m_subsong=%d\n", m_TrackNo, m_subsong);
+	}
 
-		std::vector<MatroskaChapterInfo> &chapters = scanner.GetChapters();
+	void initialize_decorder(abort_callback & p_abort) {
+		bool p_decode = false;
+		if (m_reason == input_open_decode) {
+			p_decode = true;
+		}
+		hprintf(L"Matroska: initialize_decoder(): m_TrackNo=%d\n", m_TrackNo);
+		MatroskaTrackInfo &currentTrack = m_parser->GetTrack(m_TrackNo);
+		{
+			packet_decoder::matroska_setup setup;
+			pfc::string8 codec_temp(currentTrack.codecID.c_str());
+			setup.codec_id = codec_temp;
+			setup.sample_rate = (unsigned)currentTrack.samplesPerSec;
+			setup.sample_rate_output = (unsigned)currentTrack.samplesOutputPerSec;
+			setup.channels = (unsigned)currentTrack.channels;
+			setup.codec_private_size = currentTrack.codecPrivate.size();
+			if (setup.codec_private_size)
+				setup.codec_private = &currentTrack.codecPrivate.at(0);
+			else
+				setup.codec_private = NULL;
 
-#ifdef MULTITRACK
-		if (chapters.size() > 0) {
-			for (size_t c = 0; c < chapters.size() * scanner.GetAudioTrackCount(); c++) {
-				out->on_entry(make_playable_location(filename, (int)c));
+			packet_decoder::g_open(m_decoder, p_decode, packet_decoder::owner_matroska, 0, &setup, sizeof(setup), p_abort);
+			if (m_decoder == NULL)
+			{
+				console::error(uStringPrintf("Matroska: unable to find a \"%s\" packet decoder object.", (const char*)codec_temp));
+				cleanup();
+				throw exception_io_data();
+			} else {
+				hprintf(L"Matroska: using '%S' decoder.\n", (const char*)codec_temp);
 			}
-			r->reader_release();
-			return 1;
-		} else if(scanner.GetAudioTrackCount() > 0) {
-			for (size_t t = 0; t < scanner.GetAudioTrackCount(); t++) {
-				out->on_entry(make_playable_location(filename, (int)t));
-			}
-			r->reader_release();
-			return 1;
 		}
-#else
-		if (chapters.size() > 0) {
-			for (size_t c = 0; c < chapters.size(); c++) {
-				out->on_entry(make_playable_location(filename, (int)c));
-			}
-			r->reader_release();
-			return 1;
-		}
-#endif
-
-		r->reader_release();
-		return 0;
+		m_expected_channels = currentTrack.channels;
+		m_expected_sample_rate = (unsigned)(currentTrack.samplesOutputPerSec == 0 ? currentTrack.samplesPerSec : currentTrack.samplesOutputPerSec);
+		m_expected_bitspersample = currentTrack.bitsPerSample;
 	}
 };
 
-static service_factory_single_t<track_indexer,track_indexer_matroska> foo_matroska1;
+static input_factory_t<input_matroska> g_input_matroska_factory;
 
-DECLARE_COMPONENT_VERSION("Matroska Plugin" ,"0.8.5","Copyright (C) 2003-2004 Jory Stone (jcsston at toughguy.net)\nCopyright (C) 2003-2004 Peter Pawlowski");
+DECLARE_COMPONENT_VERSION("Matroska Plugin" ,"0.9.0.7","ported to 0.9 by Haru Ayana <ayana at reharmonize.net>\nCopyright (C) 2003-2004 Jory Stone (jcsston at toughguy.net)\nCopyright (C) 2003-2004 Peter Pawlowski");
 
-
 DECLARE_FILE_TYPE("Matroska Audio files","*.MKA");

Added: trunk/foo_matroska/foo_input_matroska.rc
===================================================================
--- trunk/foo_matroska/foo_input_matroska.rc	2006-04-30 12:41:04 UTC (rev 1249)
+++ trunk/foo_matroska/foo_input_matroska.rc	2006-04-30 12:46:18 UTC (rev 1250)
@@ -0,0 +1,63 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+

Added: trunk/foo_matroska/foo_input_matroska.vcproj
===================================================================
--- trunk/foo_matroska/foo_input_matroska.vcproj	2006-04-30 12:41:04 UTC (rev 1249)
+++ trunk/foo_matroska/foo_input_matroska.vcproj	2006-04-30 12:46:18 UTC (rev 1250)
@@ -0,0 +1,341 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="foo_input_matroska"
+	ProjectGUID="{B481726C-6D1C-4711-AA8E-33CB30A7DC6D}"
+	RootNamespace="foo_input_matroska"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\../Debug"
+			IntermediateDirectory=".\Debug"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName=".\../Debug/foo_matroska.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../libebml;../../libmatroska"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FOO_MATROSKA_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				PrecompiledHeaderFile=".\Debug/foo_matroska.pch"
+				AssemblerListingLocation=".\Debug/"
+				ObjectFile=".\Debug/"
+				ProgramDataBaseFileName=".\Debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+				AdditionalIncludeDirectories=""
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="shared.lib libebmld.lib libmatroskad.lib"
+				ShowProgress="0"
+				OutputFile=".\../foobar2000/components/foo_matroska.dll"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="../shared"
+				IgnoreAllDefaultLibraries="false"
+				IgnoreDefaultLibraryNames=""
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile=".\../Debug/foo_matroska.pdb"
+				ImportLibrary=".\../Debug/foo_matroska.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\../Debug/foo_matroska.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\../Release"
+			IntermediateDirectory=".\Release"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName=".\../Release/foo_matroska.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="1"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="../../libebml,../../libmatroska"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FOO_MATROSKA_EXPORTS"
+				StringPooling="true"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile=".\Release/foo_matroska.pch"
+				AssemblerListingLocation=".\Release/"
+				ObjectFile=".\Release/"
+				ProgramDataBaseFileName=".\Release/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="shared.lib libebml.lib libmatroska.lib"
+				OutputFile=".\../Release/foo_input_matroska.dll"
+				Version=""
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="../shared"
+				IgnoreAllDefaultLibraries="false"
+				IgnoreDefaultLibraryNames=""
+				ProgramDatabaseFile=".\../Release/foo_matroska.pdb"
+				ImportLibrary=".\../Release/foo_matroska.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\../Release/foo_matroska.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+			>
+			<File
+				RelativePath="DbgOut.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="foo_input_matroska.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="matroska_parser.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl"
+			>
+			<File
+				RelativePath="DbgOut.h"
+				>
+			</File>
+			<File
+				RelativePath="Foobar2000ReaderIOCallback.h"
+				>
+			</File>
+			<File
+				RelativePath="matroska_parser.h"
+				>
+			</File>
+			<File
+				RelativePath="resource.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+			>
+			<File
+				RelativePath=".\foo_input_matroska.rc"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCResourceCompilerTool"
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCResourceCompilerTool"
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

Deleted: trunk/foo_matroska/foo_matroska.dsp

Deleted: trunk/foo_matroska/foo_matroska.rc

Modified: trunk/foo_matroska/matroska_parser.cpp
===================================================================
--- trunk/foo_matroska/matroska_parser.cpp	2006-04-30 12:41:04 UTC (rev 1249)
+++ trunk/foo_matroska/matroska_parser.cpp	2006-04-30 12:46:18 UTC (rev 1250)
@@ -194,8 +194,8 @@
 	codecPrivateReady = false;
 };
 
-MatroskaAudioParser::MatroskaAudioParser(reader *input) 
-	: m_IOCallback(input),
+MatroskaAudioParser::MatroskaAudioParser(service_ptr_t<file> input, abort_callback & p_abort) 
+	: m_IOCallback(input, p_abort),
 		m_InputStream(m_IOCallback)
 {
 	m_TimecodeScale = TIMECODE_SCALE;
@@ -206,7 +206,7 @@
 	//UpperElementLevel = 0;
 	m_CurrentEdition = 0;
 	m_CurrentChapter = 0;
-	m_FileSize = input->get_length();
+	m_FileSize = input->get_size(p_abort);
 	m_TagPos = 0;
 	m_TagSize = 0;
 	m_TagScanRange = 1024 * 64;
@@ -277,36 +277,73 @@
 						// Search for them at the end of the file
 						if (m_TagScanRange > 0)
 						{
+							TIMER;
 							m_IOCallback.setFilePointer(m_FileSize - m_TagScanRange);
-							binary Buffer[4];
-							while (m_IOCallback.read(Buffer, 3) >= 3)
-							{//0x18
-								if ((Buffer[0] == 0x54) && (Buffer[1] == 0xc3) && (Buffer[2] == 0x67))
-								{
+							uint64 init_pos = m_IOCallback.getFilePointer();
+							/*
+								BM Search
+							*/
+							binary buf[1024*64];
+							binary pat[3]; pat[0] = 0x54; pat[1] = 0xc3; pat[2] = 0x67;
+							uint64 s_pos = m_IOCallback.getFilePointer();
+							m_IOCallback.read(buf, m_TagScanRange);
+							MatroskaSearch search(buf, pat);
+							int pos = search.Match();
+							if (pos != -1) {
+								do {
+									m_IOCallback.setFilePointer(s_pos+pos+3);
 									uint64 startPos = m_IOCallback.getFilePointer();
-
-									//seek back 3 bytes, so libmatroska can find the Tags element Ebml ID
 									m_IOCallback.setFilePointer(-4, seek_current);
-
 									EbmlElement *levelUnknown = m_InputStream.FindNextID(KaxTags::ClassInfos, 0xFFFFFFFFFFFFFFFFL);
 									if ((levelUnknown != NULL) 
 										&& (m_FileSize >= startPos + levelUnknown->GetSize()) 
 										&& (EbmlId(*levelUnknown) == KaxTags::ClassInfos.GlobalId))
 									{
 										Parse_Tags(static_cast<KaxTags *>(levelUnknown));
-										delete levelUnknown;
-										levelUnknown = NULL;
+										_TIMER("MatroskaAudioParser::Parse(BM)");
 										break;
 									}
 									delete levelUnknown;
 									levelUnknown = NULL;
+									m_IOCallback.setFilePointer(s_pos);
+									pos = search.Match(pos+1);
+								} while (pos != -1);
+								/*
+									~BM Search
+								*/
+							} else {
+								m_IOCallback.setFilePointer(init_pos);
+								binary Buffer[4];
+								while (m_IOCallback.read(Buffer, 3) >= 3)
+								{//0x18
+									if ((Buffer[0] == 0x54) && (Buffer[1] == 0xc3) && (Buffer[2] == 0x67))
+									{
+										uint64 startPos = m_IOCallback.getFilePointer();
 
-									//Restore the file pos
-									m_IOCallback.setFilePointer(startPos);
+										//seek back 3 bytes, so libmatroska can find the Tags element Ebml ID
+										m_IOCallback.setFilePointer(-4, seek_current);
+
+										EbmlElement *levelUnknown = m_InputStream.FindNextID(KaxTags::ClassInfos, 0xFFFFFFFFFFFFFFFFL);
+										if ((levelUnknown != NULL) 
+											&& (m_FileSize >= startPos + levelUnknown->GetSize()) 
+											&& (EbmlId(*levelUnknown) == KaxTags::ClassInfos.GlobalId))
+										{
+											_TIMER("MatroskaAudioParser::Parse()");
+											Parse_Tags(static_cast<KaxTags *>(levelUnknown));
+											delete levelUnknown;
+											levelUnknown = NULL;
+											break;
+										}
+										delete levelUnknown;
+										levelUnknown = NULL;
+
+										//Restore the file pos
+										m_IOCallback.setFilePointer(startPos);
+									}
+									//seek back 2 bytes
+									m_IOCallback.setFilePointer(-2, seek_current);
 								}
-								//seek back 2 bytes
-								m_IOCallback.setFilePointer(-2, seek_current);
-							}					
+							}
 						} else {
 							//m_TagPos = m_FileSize;
 						}
@@ -617,10 +654,9 @@
 	return 0;
 };
 
-int MatroskaAudioParser::WriteTags(const file_info *info)
+//int MatroskaAudioParser::WriteTags(const file_info & info)
+int MatroskaAudioParser::WriteTags()
 {
-	SetTags(info);
-
 	KaxTags & MyKaxTags = GetChild<KaxTags>(*static_cast<EbmlMaster *>(m_ElementLevel0));
 
 	// On to writing :)
@@ -774,20 +810,20 @@
 		return name;
 }
 
-int meta_get_num(const file_info *info, const char* name, int idx)
+int meta_get_num(const file_info &info, const char* name, int idx)
 {
-	assert(is_valid_utf8(name));
-	int n, m = min(info->meta_get_count(), idx);
+	assert(pfc::is_valid_utf8(name));
+	int n, m = min(info.meta_get_count(), idx);
 	int rv = 0;
 	for(n=0; n<m; n++)
 	{
-		if (!stricmp_utf8(name, info->meta_enum_name(n)))
+		if (!stricmp_utf8(name, info.meta_enum_name(n)))
 			rv++;
 	}
 	return rv;
 }
 
-void MatroskaAudioParser::SetTags(const file_info *info)
+void MatroskaAudioParser::SetTags(const file_info &info)
 {
 	int i, idx;
 	const char *name, *value;	
@@ -807,22 +843,38 @@
 		if(trackTag->targetTypeValue == 0)
 			trackTag->targetTypeValue = 50;
 		trackTag->MarkAllAsRemovalPending();
-		int metaDataCount = info->meta_get_count();
+		int metaDataCount = info.meta_get_count();
 		for (i = 0; i < metaDataCount; i++)
 		{
-			name = info->meta_enum_name(i);
-			value = info->meta_enum_value(i);
-			idx = meta_get_num(info, name, i);
-			name = foobar2k_to_matroska_chapter_tag(name);
-			if ((name != NULL) && (value != NULL)) {
-				trackTag->SetTagValue(name, value, idx);
+			for (int j = 0; j != info.meta_enum_value_count(i); ++j) {
+				name = info.meta_enum_name(i);
+				value = info.meta_enum_value(i, j);
+				//idx = meta_get_num(info, name, i);
+				idx = j;
+				name = foobar2k_to_matroska_chapter_tag(name);
+				if ((name != NULL) && (value != NULL)) {
+					trackTag->SetTagValue(name, value, idx);
+				}
 			}
 		}
 		// Add the replay_gain tags
-		value = info->info_get("REPLAYGAIN_TRACK_GAIN");
+		replaygain_info rg = info.get_replaygain();
+		if (rg.is_track_gain_present()) {
+			char tmp[rg.text_buffer_size];
+			pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_gain, 7);
+			value = (const char*)tmp;
+		} else {
+			value = NULL;
+		}
 		if (value)
 			trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
-		value = info->info_get("REPLAYGAIN_TRACK_PEAK");
+		if (rg.is_track_peak_present()) {
+			char tmp[rg.text_buffer_size];
+			pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_peak, 7);
+			value = (const char*)tmp;
+		} else {
+			value = NULL;
+		}
 		if (value)
 			trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
 		trackTag->RemoveMarkedTags();
@@ -843,28 +895,44 @@
 		if(trackTag->targetTypeValue == 0)
 			trackTag->targetTypeValue = 50;
 		trackTag->MarkAllAsRemovalPending();
-		int metaDataCount = info->meta_get_count();
+		int metaDataCount = info.meta_get_count();
 		for (i = 0; i < metaDataCount; i++)
 		{
-			name = info->meta_enum_name(i);
-			value = info->meta_enum_value(i);
-			idx = meta_get_num(info, name, i);
-			if (starts_with(name, "ALBUM") ||
-				starts_with(name, "SUBALBUM") ||
-				starts_with(name, "DISCID"))
-			{
-				name = foobar2k_to_matroska_edition_tag(name);
-			} else {
-				name = NULL;
+			for (int j = 0; j != info.meta_enum_value_count(i); ++j) {
+				name = info.meta_enum_name(i);
+				value = info.meta_enum_value(i, j);
+				//idx = meta_get_num(info, name, i);
+				idx = j;
+				if (starts_with(name, "ALBUM") ||
+					starts_with(name, "SUBALBUM") ||
+					starts_with(name, "DISCID"))
+				{
+					name = foobar2k_to_matroska_edition_tag(name);
+				} else {
+					name = NULL;
+				}
+				if ((name != NULL) && (value != NULL)) {
+					trackTag->SetTagValue(name, value, idx);
+				}
 			}
-			if ((name != NULL) && (value != NULL)) {
-				trackTag->SetTagValue(name, value, idx);
-			}
 		}
-		value = info->info_get("REPLAYGAIN_ALBUM_GAIN");
+		replaygain_info rg = info.get_replaygain();
+		if (rg.is_album_gain_present()) {
+			char tmp[rg.text_buffer_size];
+			pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_album_gain, 7);
+			value = (const char*)tmp;
+		} else {
+			value = NULL;
+		}
 		if (value)
 			trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
-		value = info->info_get("REPLAYGAIN_ALBUM_PEAK");
+		if (rg.is_album_peak_present()) {
+			char tmp[rg.text_buffer_size];
+			pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_album_peak, 7);
+			value = (const char*)tmp;
+		} else {
+			value = NULL;
+		}
 		if (value)
 			trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
 		trackTag->RemoveMarkedTags();
@@ -889,28 +957,44 @@
 		if(chapterTag->targetTypeValue == 0)
 			chapterTag->targetTypeValue = 30;
 		chapterTag->MarkAllAsRemovalPending();
-		int metaDataCount = info->meta_get_count();
+		int metaDataCount = info.meta_get_count();
 		for (i = 0; i < metaDataCount; i++)
 		{
-			name = info->meta_enum_name(i);
-			value = info->meta_enum_value(i);
-			idx = meta_get_num(info, name, i);
-			if (starts_with(name, "ALBUM") ||
-				starts_with(name, "SUBALBUM") ||
-				starts_with(name, "DISCID"))
-			{
-				name = NULL;
-			} else {
-				name = foobar2k_to_matroska_chapter_tag(name);
+			for (int j = 0; j != info.meta_enum_value_count(i); ++j) {
+				name = info.meta_enum_name(i);
+				value = info.meta_enum_value(i, j);
+				//idx = meta_get_num(info, name, i);
+				idx = j;
+				if (starts_with(name, "ALBUM") ||
+					starts_with(name, "SUBALBUM") ||
+					starts_with(name, "DISCID"))
+				{
+					name = NULL;
+				} else {
+					name = foobar2k_to_matroska_chapter_tag(name);
+				}
+				if ((name != NULL) && (value != NULL)) {
+					chapterTag->SetTagValue(name, value, idx);
+				}
 			}
-			if ((name != NULL) && (value != NULL)) {
-				chapterTag->SetTagValue(name, value, idx);
-			}
 		}
-		value = info->info_get("REPLAYGAIN_TRACK_GAIN");
+		replaygain_info rg = info.get_replaygain();
+		if (rg.is_track_gain_present()) {
+			char tmp[rg.text_buffer_size];
+			pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_gain, 7);
+			value = (const char*)tmp;
+		} else {
+			value = NULL;
+		}
 		if (value)
 			chapterTag->SetTagValue("REPLAYGAIN_GAIN", value);
-		value = info->info_get("REPLAYGAIN_TRACK_PEAK");
+		if (rg.is_track_peak_present()) {
+			char tmp[rg.text_buffer_size];
+			pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_peak, 7);
+			value = (const char*)tmp;
+		} else {
+			value = NULL;
+		}
 		if (value)
 			chapterTag->SetTagValue("REPLAYGAIN_PEAK", value);
 		chapterTag->RemoveMarkedTags();
@@ -978,6 +1062,9 @@
 		return m_CurrentChapter->timeEnd - m_CurrentChapter->timeStart;
 	};
 	return m_Duration;
+	if (m_Tracks.size() != 0) {
+		return m_Tracks.at(m_CurrentTrackNo).defaultDuration * (int64)m_TimecodeScale;
+	}
 };
 
 int32 MatroskaAudioParser::GetFirstAudioTrack()
@@ -1028,7 +1115,7 @@
 	return false;
 }
 
-static is_hidden_edition_field(const char * name)
+static bool is_hidden_edition_field(const char * name)
 {
 	for (int i = 0; i < tabsize(hidden_edition_field); i++)
 		if (!stricmp_utf8(name, hidden_edition_field[i]))
@@ -1036,7 +1123,7 @@
 	return false;
 }
 
-static is_hidden_chapter_field(const char * name)
+static bool is_hidden_chapter_field(const char * name)
 {
 	for (int i = 0; i < tabsize(hidden_chapter_field); i++)
 		if (!stricmp_utf8(name, hidden_chapter_field[i]))
@@ -1198,7 +1285,7 @@
 	return AtLeastOneChapter;
 }
 
-void MatroskaAudioParser::SetAlbumTags(file_info *info,
+void MatroskaAudioParser::SetAlbumTags(file_info & info,
 									   MatroskaTagInfo* AlbumTags,
 									   MatroskaTagInfo* TrackTags)
 {
@@ -1213,11 +1300,11 @@
 		{
 			if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
 			{
-				info->info_set("REPLAYGAIN_ALBUM_GAIN",
-					simpleTag.value.GetUTF8().c_str());	
+				info.info_set_replaygain("replaygain_album_gain", simpleTag.value.GetUTF8().c_str());
+				if (TrackTags == NULL) info.info_set_replaygain("replaygain_track_gain", simpleTag.value.GetUTF8().c_str());
 			} else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
-				info->info_set("REPLAYGAIN_ALBUM_PEAK",
-					simpleTag.value.GetUTF8().c_str());	
+				info.info_set_replaygain("replaygain_album_peak", simpleTag.value.GetUTF8().c_str());
+				if (TrackTags == NULL) info.info_set_replaygain("replaygain_track_peak", simpleTag.value.GetUTF8().c_str());
 			}
 		}
 		else if (is_hidden_edition_field(simpleTag.name.GetUTF8().c_str()))
@@ -1230,9 +1317,9 @@
 			// Special case for Edition/TITLE
 			if(TagExistsAtChapterLevel(TrackTags, "ALBUM"))
 			{
-				info->meta_add("ALBUM TITLE", simpleTag.value.GetUTF8().c_str());
+				info.meta_add("ALBUM TITLE", simpleTag.value.GetUTF8().c_str());
 			} else {
-				info->meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
+				info.meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
 			}
 		}
 		else if(IsTagNamed(simpleTag,"SUBTITLE"))
@@ -1240,18 +1327,18 @@
 			// Special case for Edition/SUBTITLE
 			if(TagExistsAtChapterLevel(TrackTags, "SUBALBUM"))
 			{
-				info->meta_add("ALBUM SUBTITLE", simpleTag.value.GetUTF8().c_str());
+				info.meta_add("ALBUM SUBTITLE", simpleTag.value.GetUTF8().c_str());
 			} else {
-				info->meta_add("SUBALBUM", simpleTag.value.GetUTF8().c_str());
+				info.meta_add("SUBALBUM", simpleTag.value.GetUTF8().c_str());
 			}
 		}
 		else if(IsTagNamed(simpleTag,"DISCID"))
 		{
-			info->meta_add("DISCID", simpleTag.value.GetUTF8().c_str());
+			info.meta_add("DISCID", simpleTag.value.GetUTF8().c_str());
 		}
 		else if(IsTagNamed(simpleTag,"COMMENTS"))
 		{
-			info->meta_add("ALBUM COMMENT", simpleTag.value.GetUTF8().c_str());
+			info.meta_add("ALBUM COMMENT", simpleTag.value.GetUTF8().c_str());
 		}
 		else if((!AreTagsIdenticalAtAllLevels(simpleTag.name.GetUTF8().c_str()))
 			|| (!TagExistsAtChapterLevel(TrackTags, simpleTag.name.GetUTF8().c_str())))
@@ -1259,7 +1346,7 @@
 			// Prefix tag with "ALBUM "
 			char newTagName[255] = "ALBUM ";
 			strncat(newTagName, matroska_to_foobar2k_edition_tag(simpleTag.name.GetUTF8().c_str()),255);
-			info->meta_add(newTagName, simpleTag.value.GetUTF8().c_str());					
+			info.meta_add(newTagName, simpleTag.value.GetUTF8().c_str());					
 		}
 		else 
 		{
@@ -1269,7 +1356,7 @@
 	}
 }
 
-void MatroskaAudioParser::SetTrackTags(file_info *info, MatroskaTagInfo* TrackTags)
+void MatroskaAudioParser::SetTrackTags(file_info &info, MatroskaTagInfo* TrackTags)
 {
 	if(TrackTags == NULL)
 		return;
@@ -1282,11 +1369,9 @@
 		{
 			if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
 			{
-				info->info_set("REPLAYGAIN_TRACK_GAIN",
-					simpleTag.value.GetUTF8().c_str());	
+				info.info_set_replaygain("replaygain_track_gain", simpleTag.value.GetUTF8().c_str());
 			} else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
-				info->info_set("REPLAYGAIN_TRACK_PEAK",
-					simpleTag.value.GetUTF8().c_str());	
+				info.info_set_replaygain("replaygain_track_peak", simpleTag.value.GetUTF8().c_str());
 			}
 		}
 		else if (is_hidden_chapter_field(simpleTag.name.GetUTF8().c_str()))
@@ -1296,33 +1381,33 @@
 		}
 		else if(IsTagNamed(simpleTag,"COMMENTS"))
 		{
-			info->meta_add("COMMENT", simpleTag.value.GetUTF8().c_str());
+			info.meta_add("COMMENT", simpleTag.value.GetUTF8().c_str());
 		}
 		else if(IsTagNamed(simpleTag,"ALBUM"))
 		{
 			if(!TagExistsAtEditionLevel(TrackTags, "TITLE") && AreTagsIdenticalAtChapterLevel("ALBUM")) {
-				info->meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
+				info.meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
 			} else {
-				info->meta_add("ORIGINAL_ALBUM", simpleTag.value.GetUTF8().c_str());
+				info.meta_add("ORIGINAL_ALBUM", simpleTag.value.GetUTF8().c_str());
 			}
 		}
 		else
 		{
-			info->meta_add(
+			info.meta_add(
 				matroska_to_foobar2k_chapter_tag(simpleTag.name.GetUTF8().c_str()),
 				simpleTag.value.GetUTF8().c_str());	
 		}
 	}
 }
 
-bool MatroskaAudioParser::SetFB2KInfo(file_info *info)
+bool MatroskaAudioParser::SetFB2KInfo(file_info &info, t_uint32 p_subsong)
 {
 	if (m_MuxingApp.length() > 0)
-		info->info_set("MUXING_APP", m_MuxingApp.GetUTF8().c_str());
+		info.info_set("MUXING_APP", m_MuxingApp.GetUTF8().c_str());
 	if (m_WritingApp.length() > 0)
-		info->info_set("WRITING_APP", m_WritingApp.GetUTF8().c_str());
+		info.info_set("WRITING_APP", m_WritingApp.GetUTF8().c_str());
 	if (m_FileTitle.length() > 0)
-		info->info_set("TITLE", m_FileTitle.GetUTF8().c_str());
+		info.info_set("TITLE", m_FileTitle.GetUTF8().c_str());
 
 	MatroskaTagInfo *TrackTags = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
 	MatroskaTagInfo *ChapterTags = NULL;
@@ -1359,27 +1444,27 @@
 	{
 		// If TITLE tag is empty we get it from the chapter name
 		if ( (m_CurrentChapter->display.size() > 0) &&
-			 ((info->meta_get("TITLE") == NULL) ||
-			  (strlen(info->meta_get("TITLE")) == 0) ) )
+			 ((info.meta_get("TITLE", 0) == NULL) ||
+			  (strlen(info.meta_get("TITLE", 0)) == 0) ) )
 		{
-			info->meta_set("TITLE", m_CurrentChapter->display.at(0).string.GetUTF8().c_str());
+			info.meta_set("TITLE", m_CurrentChapter->display.at(0).string.GetUTF8().c_str());
 		}
-		if ((info->meta_get("TRACKNUMBER") == NULL) || (strlen(info->meta_get("TRACKNUMBER")) == 0))
+		if ((info.meta_get("TRACKNUMBER", 0) == NULL) || (strlen(info.meta_get("TRACKNUMBER", 0)) == 0))
 		{
 			char trackNumberString[32];
 #ifdef MULTITRACK			
-			wsprintf(trackNumberString, "%d",
-				(info->get_subsong_index() % m_Chapters.size()) +1);
+			wsprintf((LPWSTR)trackNumberString, (LPCWSTR)"%d",
+				(p_subsong % m_Chapters.size()) +1);
 #else
 			
-			wsprintf(trackNumberString, "%d",info->get_subsong_index()+1);
+			wsprintf(trackNumberString, "%d",p_subsong+1);
 #endif
-			info->meta_set("TRACKNUMBER", trackNumberString);
+			info.meta_set("TRACKNUMBER", trackNumberString);
 		}
-		if ((info->meta_get("ALBUM") == NULL) || (strlen(info->meta_get("ALBUM")) == 0))
+		if ((info.meta_get("ALBUM", 0) == NULL) || (strlen(info.meta_get("ALBUM", 0)) == 0))
 		{
 			if(m_FileTitle.length() > 0)
-				info->meta_set("ALBUM", m_FileTitle.GetUTF8().c_str());
+				info.meta_set("ALBUM", m_FileTitle.GetUTF8().c_str());
 		}			
 	}
 
@@ -1392,8 +1477,8 @@
 	// do nothing, so we will only mark hidden tags.
 	// Hidden tag will be copied to keep track of them.
 	// This is needed cause tag are read and written in 2 different instances
-	dummy_file_info info;
-	SetFB2KInfo(&info);
+	file_info_impl info;
+	SetFB2KInfo(info, 0);
 };
 
 void MatroskaAudioParser::SetCurrentTrack(uint32 newTrackNo)
@@ -2376,3 +2461,57 @@
 
 	}
 };
+
+bool MatroskaSearch::Skip()
+{
+	int j;
+
+	for (j = 0; j < SEARCH_TABLE_SIZE; j++) skip[j] = SEARCH_PATTERN_SIZE;
+	for (j = 0; j < SEARCH_PATTERN_SIZE - 1; j++)
+		skip[pattern[j] & 0x00ff] = SEARCH_PATTERN_SIZE-1-j;
+	return true;
+}
+
+bool MatroskaSearch::Next()
+{
+	int  j, k, s;
+	int  *g;
+
+	if ((g = (int *)malloc(sizeof(int)*SEARCH_PATTERN_SIZE)) == NULL) return false;
+	for (j = 0; j < SEARCH_PATTERN_SIZE; j++) next[j] = 2*SEARCH_PATTERN_SIZE - 1 - j;
+	j = SEARCH_PATTERN_SIZE;
+	for (k = SEARCH_PATTERN_SIZE - 1; k >= 0; k--) {
+		g[k] = j;
+		while (j != SEARCH_PATTERN_SIZE && pattern[j] != pattern[k]) {
+			next[j] = (next[j] <= SEARCH_PATTERN_SIZE-1-k) ? next[j] : SEARCH_PATTERN_SIZE-1-k;
+			j = g[j];
+		}
+		j--;
+	}
+	s = j;
+	for (j = 0; j < SEARCH_PATTERN_SIZE; j++) {
+		next[j] = (next[j] <= s+SEARCH_PATTERN_SIZE-j) ? next[j] : s+SEARCH_PATTERN_SIZE-j;
+		if (j >= s) s = g[s];
+	}
+	free(g);
+	return true;
+}
+
+int MatroskaSearch::Match(unsigned int start)
+{
+	int i, j;
+
+	i = SEARCH_PATTERN_SIZE - 1 + start;
+	while (i < SEARCH_SOURCE_SIZE) {
+		j = SEARCH_PATTERN_SIZE - 1;
+		while (j >= 0 && source[i] == pattern[j]) {
+			i--;
+			j--;
+		}
+		if (j < 0) return i + 1;
+		if (skip[source[i] & 0x00ff] >= next[j])
+			i += skip[source[i] & 0x00ff];
+		else i += next[j];
+	}
+	return -1;
+};
\ No newline at end of file

Modified: trunk/foo_matroska/matroska_parser.h
===================================================================
--- trunk/foo_matroska/matroska_parser.h	2006-04-30 12:41:04 UTC (rev 1249)
+++ trunk/foo_matroska/matroska_parser.h	2006-04-30 12:46:18 UTC (rev 1250)
@@ -26,6 +26,7 @@
 #define MULTITRACK 1
 
 #include "../SDK/foobar2000.h"
+#include "../../pfc/pfc.h"
 #include "Foobar2000ReaderIOCallback.h"
 #include "DbgOut.h"
 #include <queue>
@@ -86,6 +87,9 @@
 #define new DEBUG_CLIENTBLOCK
 #endif
 
+#ifdef _DEBUG
+#endif
+
 using namespace LIBEBML_NAMESPACE;
 using namespace LIBMATROSKA_NAMESPACE;
 
@@ -195,14 +199,14 @@
     uint8 channels; 
     float samplesPerSec; 
 		float samplesOutputPerSec;     
-    uint8 bitsPerSample;     
+    uint8 bitsPerSample;
 		uint32 avgBytesPerSec; 
 		float defaultDuration;
 };
 
 class MatroskaAudioParser {
 public:
-	MatroskaAudioParser(reader *input);
+	MatroskaAudioParser(service_ptr_t<file> input, abort_callback & p_abort);
 	~MatroskaAudioParser();
 
 	/// The main header parsing function
@@ -213,7 +217,9 @@
 	/// \param info All the tags we need to write
 	/// \return 0 Tags written A OK
 	/// \return 1 Failed to write tags
-	int WriteTags(const file_info *info);
+	int WriteTags();
+	/// Set the info tags to the current tags file in memory
+	void SetTags(const file_info &info);
 
 	MatroskaTrackInfo &GetTrack(uint16 trackNo) { return m_Tracks.at(trackNo); };
 	uint64 GetTimecodeScale() { return m_TimecodeScale; };
@@ -227,7 +233,7 @@
 
 	/// Set the fb2k info from the matroska file
 	/// \param info This will be filled up with tags ;)
-	bool SetFB2KInfo(file_info *info);
+	bool SetFB2KInfo(file_info &info, t_uint32 p_subsong);
 
 	/// Get the foobar2000 style format string
 //	const char *GetFoobar2000Format(uint16 trackNo, bool bSetupCodecPrivate = true);
@@ -283,9 +289,8 @@
 	// \return false Nope
 	bool FindChapterUID(uint64 uid);
 	/// Adds the info tags to the current file in memory 
-	void AddTags(const file_info *info);
-	/// Set the info tags to the current tags file in memory
-	void SetTags(const file_info *info);
+	void AddTags(file_info &info);
+	
 	MatroskaTagInfo *FindTagWithTrackUID(uint64 trackUID);
 	MatroskaTagInfo *FindTagWithEditionUID(uint64 editionUID, uint64 trackUID = 0);
 	MatroskaTagInfo *FindTagWithChapterUID(uint64 chapterUID, uint64 trackUID = 0);
@@ -294,8 +299,8 @@
 	bool AreTagsIdenticalAtChapterLevel(const char * name);
 	void MarkHiddenTags();
 
-	void SetAlbumTags(file_info *info, MatroskaTagInfo* AlbumTags, MatroskaTagInfo* TrackTags);
-	void SetTrackTags(file_info *info, MatroskaTagInfo* TrackTags);
+	void SetAlbumTags(file_info &info, MatroskaTagInfo* AlbumTags, MatroskaTagInfo* TrackTags);
+	void SetTrackTags(file_info &info, MatroskaTagInfo* TrackTags);
 		
 
 	Foobar2000ReaderIOCallback m_IOCallback;
@@ -331,7 +336,8 @@
 	uint32 m_TagSize;
 	uint32 m_TagScanRange;
 
-	mem_block_fastalloc<BYTE> m_framebuffer;
+	pfc::alloc_fast<BYTE> m_framebuffer;
+	//mem_block_factalloc<BYTE> m_framebuffer;
 	//int UpperElementLevel;
 private:
 	// We have no need for these
@@ -341,37 +347,29 @@
 
 void PrintChapters(std::vector<MatroskaChapterInfo> &theChapters);
 
-class dummy_playable_location : public playable_location
+class MatroskaSearch
 {
-	const char * get_path() const { return NULL; }
-	void set_path(const char*) {}	
-	int get_number() const { return 0; }
-	void set_number(int) { };	
-};
-
-class dummy_file_info : public file_info
-{
 private:
-	dummy_playable_location m_pl;
+	static const int SEARCH_SOURCE_SIZE = 1024*64;
+	static const int SEARCH_TABLE_SIZE = SEARCH_SOURCE_SIZE;
+	static const int SEARCH_PATTERN_SIZE = 3;
+    binary * source, * pattern;
+	int pos;
+    int  next[SEARCH_TABLE_SIZE], skip[SEARCH_TABLE_SIZE];
+	bool Skip();
+	bool Next();
 public:
-	int meta_get_count(void) const { return 0; }
-	const char *meta_enum_name(int) const { return NULL; }
-	const char *meta_enum_value(int) const { return NULL; }
-	void meta_modify_value(int,const char *) { }
-	void meta_insert(int,const char *,const char *) { }
-	void meta_add(const char *,const char *) { }
-	void meta_remove(int) { }
-	void meta_remove_all(void) { }
-	void info_set(const char *,const char *) { }
-	int info_get_count(void) const { return 0; }
-	const char *info_enum_name(int) const { return NULL; }
-	const char *info_enum_value(int) const { return NULL; }
-	void info_remove(int) { }
-	void info_remove_all(void) { }
-	const class playable_location *get_location(void) const { return &m_pl; }
-	void set_location(const class playable_location *) { }
-	void set_length(double) { }
-	double get_length(void) const { return 0; }
+	MatroskaSearch(binary * p_source, binary * p_pattern)
+	{
+		ZeroMemory(next, sizeof(next));
+		ZeroMemory(skip, sizeof(skip));
+		source = p_source;
+		pattern = p_pattern;
+		Skip();
+		Next();
+	}
+	~MatroskaSearch() {};
+	int Match(unsigned int start = 0);
 };
 
 #endif // _MATROSKA_PARSER_H_



More information about the Matroska-cvs mailing list