No dobra, rozumiem, że ja... Jako, że się chwilę nudziłem to odpaliłem upx-a (plugin skompresowany, zwykłe -d starczy), disasma i debugger, sprawa naprawdę banalna.
class IrfanMP3Plugin
{
const string pluginPath = "MP3.dll";
[DllImport(
pluginPath,
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.Cdecl)]
public static extern void GetPlugInInfo(
StringBuilder version,
StringBuilder knownExtensions
);
[DllImport(
pluginPath,
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.Cdecl)]
public static extern void Play_MP3_File(
string fileName,
IntPtr parentWindow,
bool hidePlayer,
string command
);
[DllImport(pluginPath)]
public static extern void CloseMP3Player();
}
To tak:
-
GetPlugInInfo łyka dwa char* i zapisuje w nich swoje klamoty, z punktu widzenia C# wypadałoby użyć StringBuildery o sensownym rozmiarze:
-
version - string z wersją pluginu,
-
knownExtensions - string zawierający rozdzielone spacją rozszerzenia obsługiwanych formatów;
-
Play_MP3_File to w praktyce jedyna naprawdę konieczna funkcja;
-
fileName - oczywiste;
-
parentWindow, konieczny jeżeli interface odtwarzacza ma być widoczny;
-
hidePlayer - chyba jasne, nie ma znaczenia, gdy parentWindow ma wartość IntPtr.Zero;
-
command - teoretycznie przy pierwszym wywołaniu "", przy kolejnych "reload".
-
CloseMP3Player - chyba oczywiste, wypadałoby wywołać zawsze przy zamykaniu programu.
To teraz kilka uwag co do pierwszego użycia:
-
Play_MP3_File powinno otrzymać komendę "", w praktyce można zawsze przekazywać "reload",
- jeżeli okno odtwarzacza ma być ukryte to parentWindow powinno być zerowe, inaczej pojawi się na ułamek sekundy, mimo ustawionego hideWindow; hideWindow ma znaczenie dopiero przy kolejnych wywołaniach.
No dobra, tyle zauważyłem tak na szybko. Strasznie prowizoryczna aplikacja co z tego korzysta, nie czepiać się potforków:
public partial class MainWindow : Form
{
public MainWindow()
{
InitializeComponent();
StringBuilder ver = new StringBuilder(4096);
StringBuilder ext = new StringBuilder(4096);
IrfanMP3Plugin.GetPlugInInfo(ver, ext);
string[] exts = ext.ToString().Split(new char[]{' '});
openDialog.Filter =
String.Format("Supported files ({0})|{0})",
String.Join(";",
(from e in exts select "*." + e).ToArray()));
lblVersion.Text = "Plugin version: " + ver;
}
private void btnOpen_Click(object sender, EventArgs e)
{
if (openDialog.ShowDialog() == DialogResult.OK)
{
lblFileName.Text = openDialog.FileName;
btnPlay.Enabled = true;
}
}
private void btnPlay_Click(object sender, EventArgs e)
{
IrfanMP3Plugin.Play_MP3_File(
openDialog.FileName,
chbHide.Checked ? IntPtr.Zero : Handle,
chbHide.Checked,
"reload");
btnClose.Enabled = true;
}
private void btnClose_Click(object sender, EventArgs e)
{
IrfanMP3Plugin.CloseMP3Player();
btnClose.Enabled = false;
}
private void MainWindow_FormClosed(object sender, FormClosedEventArgs e)
{
IrfanMP3Plugin.CloseMP3Player();
}
}
btnOpen, btnPlay, btnClose - buttony, chbHide - checkbox, lblFileName - label, openDialog - openFileDialog - cała filozofia.
W sensownym użyciu można by to iDisposable poskładać, dorzucić wysyłanie "" itd. ale to nie mój problem.
Jeżeli autor wątku chciałby też interface innych pluginów to raczej powinien przygotować pieniążki.