/*
replacereaderclr: test program for mpg123clr, showing how to use ReplaceReader in a CLR enviro.
copyright 2009 by the mpg123 project - free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written by Malcolm Boczek
not to be used as an example of good coding practices, note the total absence of error handling!!!
*/
/*
1.9.0.0 24-Sep-09 Function names harmonized with libmpg123 (mb)
1.12.0.0 14-Apr-10 Added ReplaceReaderHandle sample code (mb)
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; // for ReplaceReaderHandle example
using System.Runtime.InteropServices; // for ReplaceReaderHandle example
using mpg123clr;
namespace ReplaceReaderclr
{
class Program
{
private unsafe static int MyReadFunc(int a, void* b, uint c)
{
// need to call posix read function here...
// PosixRead is an example, substitute your replacement function here.
int ret = mpg123.PosixRead(a, b, c);
return ret;
}
private static int MySeekFunc(int a, int b, int c)
{
// NOTE: Largefile conflict with use of "int" position values.
// Convert to long if off_t is defined as long long
// need to call posix lseek function here...
// PosixSeek is an example, substitute your replacement function here.
int ret = mpg123.PosixSeek(a, b, c);
return ret;
}
private unsafe static int MyHandleReadFunc(void* a, void* b, uint c)
{
GCHandle gch = GCHandle.FromIntPtr((IntPtr)a);
BinaryReader br = (BinaryReader)gch.Target;
byte[] buf = br.ReadBytes((int)c);
// NOTE: no discernible performance difference between Marshal.Copy and ptr++ loop
Marshal.Copy(buf, 0, (IntPtr)b, buf.Length);
// byte* ptr = (byte*)b;
// for (int i = 0, l = buf.Length; i < l; i++)
// *(ptr++) = buf[i];
return buf.Length;
}
private unsafe static int MyHandleSeekFunc(void* a, int b, int c)
{
// NOTE: Largefile conflict with use of "int" position values.
// Convert to long if off_t is defined as long long
GCHandle gch = GCHandle.FromIntPtr((IntPtr)a);
BinaryReader br = (BinaryReader)gch.Target;
return (int)br.BaseStream.Seek(b, (SeekOrigin)c);
}
private unsafe static void MyHandleCleanFunc(void* a)
{
GCHandle gch = GCHandle.FromIntPtr((IntPtr)a);
BinaryReader br = (BinaryReader)gch.Target;
br.Close();
}
static unsafe void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("I need a file to work on:\n\nPress any key to exit.");
while (Console.Read() == 0) ;
return;
}
mpg123clr.mpg.ErrorCode err;
string filename = args[0];
err = mpg123.mpg123_init();
Console.WriteLine("Init:");
RunReplaceReaderTest(filename);
RunReplaceReaderHandleTest(filename);
RunFrameByFrameTest(filename);
Console.WriteLine("\nPress any key to exit:");
while (Console.Read() == 0) ;
mpg123.mpg123_exit();
}
static unsafe void RunReplaceReaderTest(string filename)
{
mpg123clr.mpg.ErrorCode err;
mpg123 mp = new mpg123();
err = mp.mpg123_new();
// ReplaceReader example
mpg123clr.mpg123.ReadDelegate rdel = MyReadFunc;
mpg123clr.mpg123.SeekDelegate sdel = MySeekFunc;
err = mp.mpg123_replace_reader(rdel, sdel);
//err = mp.mpg123_open(args[0]);
err = mp.mpg123_open(filename);
if (err != mpg123clr.mpg.ErrorCode.ok)
{
Console.WriteLine("Error: " + mp.mpg123_strerror());
}
else
{
Console.WriteLine("Open:");
// Show available decoders
string[] Decoders = mp.mpg123_decoders();
if (Decoders.Length > 0)
{
Console.WriteLine("\nDecoders:");
foreach (string str in Decoders) Console.WriteLine(str);
}
// Show supported decoders
string[] supDecoders = mp.mpg123_supported_decoders();
if (supDecoders.Length > 0)
{
Console.WriteLine("\nSupported Decoders:");
foreach (string str in supDecoders) Console.WriteLine(str);
}
// Show actual decoder
Console.WriteLine("\nDecoder: " + mp.mpg123_current_decoder());
// Show estimated file length
Console.WriteLine("\nLength Estimate: " + mp.mpg123_length().ToString());
// Scan - gets actual details including ID3v2 and Frame offsets
err = mp.mpg123_scan();
// Show actual file length
if (err == mpg123clr.mpg.ErrorCode.ok) Console.WriteLine("Length Actual : " + mp.mpg123_length().ToString());
// Get ID3 data
mpg123clr.id3.mpg123id3v1 iv1;
mpg123clr.id3.mpg123id3v2 iv2;
err = mp.mpg123_id3(out iv1, out iv2);
// Show ID3v2 data
Console.WriteLine("\nTitle : " + iv2.title);
Console.WriteLine("Artist : " + iv2.artist);
Console.WriteLine("Album : " + iv2.album);
Console.WriteLine("Comment: " + iv2.comment);
Console.WriteLine("Year : " + iv2.year);
// Demo seek (back to start of file - note: scan should already have done this)
long pos = mp.mpg123_seek(0, System.IO.SeekOrigin.Begin);
long[] frameindex;
long step;
err = mp.mpg123_index(out frameindex, out step);
if (err == mpg123clr.mpg.ErrorCode.ok)
{
Console.WriteLine("\nFrameIndex:");
foreach (long idx in frameindex)
{
// Console.WriteLine(idx.ToString());
}
}
int num;
uint cnt;
IntPtr audio;
// Walk the file - effectively decode the data without using it...
Console.WriteLine("\nWalking : " + iv2.title);
DateTime dte, dts = DateTime.Now;
while (err == mpg123clr.mpg.ErrorCode.ok || err == mpg123clr.mpg.ErrorCode.new_format)
{
err = mp.mpg123_decode_frame(out num, out audio, out cnt);
// do something with "audio" here....
}
dte = DateTime.Now;
TimeSpan ts = dte - dts;
Console.WriteLine("Duration: " + ts.ToString());
mp.mpg123_close();
}
mp.Dispose();
}
static unsafe void RunReplaceReaderHandleTest(string filename)
{
mpg123clr.mpg.ErrorCode err;
mpg123 mp = new mpg123();
err = mp.mpg123_new();
// ReplaceReader example
mpg123clr.mpg123.ReadHandleDelegate rdel = MyHandleReadFunc;
mpg123clr.mpg123.SeekHandleDelegate sdel = MyHandleSeekFunc;
mpg123clr.mpg123.CleanupHandleDelegate cdel = MyHandleCleanFunc;
err = mp.mpg123_replace_reader_handle(rdel, sdel, cdel);
//err = mp.mpg123_open(args[0]);
BinaryReader br = new BinaryReader(File.OpenRead(filename));
err = mp.mpg123_open_handle(br);
if (err != mpg123clr.mpg.ErrorCode.ok)
{
Console.WriteLine("Error: " + mp.mpg123_strerror());
}
else
{
Console.WriteLine("Open:");
// Show available decoders
string[] Decoders = mp.mpg123_decoders();
if (Decoders.Length > 0)
{
Console.WriteLine("\nDecoders:");
foreach (string str in Decoders) Console.WriteLine(str);
}
// Show supported decoders
string[] supDecoders = mp.mpg123_supported_decoders();
if (supDecoders.Length > 0)
{
Console.WriteLine("\nSupported Decoders:");
foreach (string str in supDecoders) Console.WriteLine(str);
}
// Show actual decoder
Console.WriteLine("\nDecoder: " + mp.mpg123_current_decoder());
// Show estimated file length
Console.WriteLine("\nLength Estimate: " + mp.mpg123_length().ToString());
// Scan - gets actual details including ID3v2 and Frame offsets
err = mp.mpg123_scan();
// Show actual file length
if (err == mpg123clr.mpg.ErrorCode.ok) Console.WriteLine("Length Actual : " + mp.mpg123_length().ToString());
// Get ID3 data
mpg123clr.id3.mpg123id3v1 iv1;
mpg123clr.id3.mpg123id3v2 iv2;
err = mp.mpg123_id3(out iv1, out iv2);
// Show ID3v2 data
Console.WriteLine("\nTitle : " + iv2.title);
Console.WriteLine("Artist : " + iv2.artist);
Console.WriteLine("Album : " + iv2.album);
Console.WriteLine("Comment: " + iv2.comment);
Console.WriteLine("Year : " + iv2.year);
// Demo seek (back to start of file - note: scan should already have done this)
long pos = mp.mpg123_seek(0, System.IO.SeekOrigin.Begin);
long[] frameindex;
long step;
err = mp.mpg123_index(out frameindex, out step);
if (err == mpg123clr.mpg.ErrorCode.ok)
{
Console.WriteLine("\nFrameIndex:");
foreach (long idx in frameindex)
{
// Console.WriteLine(idx.ToString());
}
}
int num;
uint cnt;
IntPtr audio;
// Walk the file - effectively decode the data without using it...
Console.WriteLine("\nWalking : " + iv2.title);
DateTime dte, dts = DateTime.Now;
while (err == mpg123clr.mpg.ErrorCode.ok || err == mpg123clr.mpg.ErrorCode.new_format)
{
err = mp.mpg123_decode_frame(out num, out audio, out cnt);
// do something with "audio" here....
}
dte = DateTime.Now;
TimeSpan ts = dte - dts;
Console.WriteLine("Duration: " + ts.ToString());
mp.mpg123_close();
}
mp.Dispose();
}
static unsafe void RunFrameByFrameTest(string filename)
{
mpg123clr.mpg.ErrorCode err;
mpg123 mp = new mpg123();
err = mp.mpg123_new();
err = mp.mpg123_open(filename);
if (err != mpg123clr.mpg.ErrorCode.ok)
{
Console.WriteLine("Error: " + mp.mpg123_strerror());
}
else
{
Console.WriteLine("Open:");
// Show available decoders
string[] Decoders = mp.mpg123_decoders();
if (Decoders.Length > 0)
{
Console.WriteLine("\nDecoders:");
foreach (string str in Decoders) Console.WriteLine(str);
}
// Show supported decoders
string[] supDecoders = mp.mpg123_supported_decoders();
if (supDecoders.Length > 0)
{
Console.WriteLine("\nSupported Decoders:");
foreach (string str in supDecoders) Console.WriteLine(str);
}
// Show actual decoder
Console.WriteLine("\nDecoder: " + mp.mpg123_current_decoder());
// Show estimated file length
Console.WriteLine("\nLength Estimate: " + mp.mpg123_length().ToString());
// Scan - gets actual details including ID3v2 and Frame offsets
err = mp.mpg123_scan();
// Show actual file length
if (err == mpg123clr.mpg.ErrorCode.ok) Console.WriteLine("Length Actual : " + mp.mpg123_length().ToString());
// Get ID3 data
mpg123clr.id3.mpg123id3v1 iv1;
mpg123clr.id3.mpg123id3v2 iv2;
err = mp.mpg123_id3(out iv1, out iv2);
// Show ID3v2 data
Console.WriteLine("\nTitle : " + iv2.title);
Console.WriteLine("Artist : " + iv2.artist);
Console.WriteLine("Album : " + iv2.album);
Console.WriteLine("Comment: " + iv2.comment);
Console.WriteLine("Year : " + iv2.year);
// Demo seek (back to start of file - note: scan should already have done this)
long pos = mp.mpg123_seek(0, System.IO.SeekOrigin.Begin);
long[] frameindex;
long step;
err = mp.mpg123_index(out frameindex, out step);
if (err == mpg123clr.mpg.ErrorCode.ok)
{
Console.WriteLine("\nFrameIndex:");
foreach (long idx in frameindex)
{
// Console.WriteLine(idx.ToString());
}
}
int num;
uint cnt;
IntPtr audio;
// Walk the file - effectively decode the data without using it...
Console.WriteLine("\nFrame Walking : " + iv2.title);
DateTime dte, dts = DateTime.Now;
while (err == mpg123clr.mpg.ErrorCode.ok || err == mpg123clr.mpg.ErrorCode.new_format)
{
err = mp.mpg123_framebyframe_decode(out num, out audio, out cnt);
err = mp.mpg123_framebyframe_next();
// do something with "audio" here....
}
dte = DateTime.Now;
TimeSpan ts = dte - dts;
Console.WriteLine("Duration: " + ts.ToString());
mp.mpg123_close();
}
mp.Dispose();
}
}
}