Problem MP3Player mit Quartz.DLL spielt Kanon

Rando

Mitglied
Moin Leute,

Hatte den Thread gestern irrtümlich im C++ Forum erstellt und poste ihn nun hier nochmal in der Hoffnung, dass er nun an richtiger Forenstelle mehr Lösungsansätze generiert.

So zu meinem Problem:

Ich habe unter Verwendung der Quartz.dll in C# einen MP3Player gebastelt, der nur sehr rudimentäre Basis Funktionen implementiert (Abspielen, Stop, Pause und Resume).

Jetzt mein Problem:
wenn ich eine Datei öffne mit:

MP3Player.RenderFile(value); ---> [value ist hierbei der String des Dateinnamens]
MP3Player.Run();

und dann während das Stück gespielt wird ein neues öffnen möchte, passiert nicht das was ich erwarten würde, nämlich, dass das derzeit spielende Stück abbricht und durch das neue Stück ersetzt wird, sondern das 2. Stück wird paralell gestartet und ich habe so eine Art Kanon-Effekt, was wirklich nicht sooo der Brüller ist.

Ich bin nun nicht so der Crack und relativ neu in der Programmierwelt, weshalb ich hoffe, dass jemand von euch mir einen Rat geben kann, wie ich das Problem lösen kann.

Thx und Greeds
Rando
 
Post doch bitte mal ein bisserl mehr Sourcecode wie das bei Dir ausschaut. Scheint nämlich, also würdest du mehrere Instanzen von deinem Player starten,die dann natürlich gleichzeitig spielen.

mfG,
Nitro
 
Gerne

Code:
using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Windows.Forms; 
using System.Threading;
using QuartzTypeLib;

public class MP3_View : Chip_View{
	private FilgraphManager MP3Player = new FilgraphManager();

	public MP3_View()
	{
	assembly_name=Application.StartupPath+"\\"+"MP3_Chip.exe";
	SetPrimarySlot("MP3-File");
	Text="MP3_Pad";
	Size=new Size(100,100);
    }

    public override void CreateGUI(){
	... HIER WIRD EIN KLEINES GUI DEFINIERT
    }

    public override void ChangeBorder(){
	... DIESE METHODE KANN DEN FRAME UM MEINE APPLIKATION AN- und AUSSCHALTEN 
    }
    
    
	public override void UpdateView(String slotname, String value)
	{
		if(slotname=="MP3-File")
		Start_Filename(value);
	}

	private void Start_Filename(String value)
	{
		try
		{
			((Label)gui).Text=value;
			Set_Title(value);
			MP3Player.RenderFile(value);
			MP3Player.Run();
		}
		catch(Exception){MessageBox.Show("No such file!");}
	}
	
	protected void Set_Title(String value)
	{
		this.Text=value;
	}

	public override void CreateMenu()
	{
		base.CreateMenu();
		AddMenuItem("-");
		AddMenuItemWithHandler("Pause");
		AddMenuItemWithHandler("Resume");
		AddMenuItemWithHandler("Stop");
	}
    
	public override void HandleMenuEvent(Object sender,EventArgs e)
	{
		MenuItem item=(MenuItem)sender;
		switch(item.Text)
		{
			case "Pause":
				Cursor.Current = Cursors.WaitCursor;
				MP3Player.Pause();
				Cursor.Current = Cursors.Default;
				break;
			case "Resume":
				Cursor.Current = Cursors.WaitCursor;
				MP3Player.Run();
				Cursor.Current = Cursors.Default;
				break;
			case "Stop":
				MP3Player.Stop();
				break;
			default:
				base.HandleMenuEvent(sender, e);
				break;
		}
	}

    public static Chip_View CreateInstance(){
	MP3_View view= new MP3_View();
	view.model= new MP3_Model(view);   
	return view;
    }
    
    [STAThread]
    public static void Main(){
	Chip_View view= CreateInstance();
	Application.Run(view);
    }
}

Also ich habe auch bereits mit der RSPplayerDLL aus dem Netz gespielt, die dort als Shareware downloadbar ist. Das Muster der Einbindung war ABSOLUT identisch, nur störte mich dabei, dass in unregelmässigen Abständen ein Shareware-PopUp auftauchte, deshalb wollte ich auf die Quartz.DLL umstellen und erlebe nun dieses Phänomen.

(Bitte Code-Tags verwenden, danke. Alex)
 
Zuletzt bearbeitet von einem Moderator:
Mit dieser Klasse instanzierst jedes Mal eine neue Chip_View und diese läuft wiederum in einem Thread. Dadurch wird der Song auch nicht abgebrochen.

Du musst immer mit der gleichen Instanz arbeiten. Sprich, Du darfst nur einmal deine Main() aufrufen und mit der erhaltenen Instanz musst du dann arbeiten.

mfG,
Nitro
 
Hm, ich denke nicht, dass es daran liegt, denn der MP3Player ist zwar von der Klasse Chip_View abgeleitet (gibt es das Wort abgelitten?), aber er wird beim Aufruf nur einmal instanziiert.

Auch der FilgraphManager der Quartz.dll wird nur einmal instanziiert. Nach erstmaligen Aufruf einer MP3Datei über die Funktion

Start_Filename(value)

bei der ja der komplette Pfad + Dateiname übergeben wird funktioniert ja alles prächtig. Über die CASE Statements kann ich auch das Abspielverhalten des Players prima steuern.

Was meiner Meinung nach fehlt (und das habe ich glaube ich auch schon bei den mciSendString - Kommandos der WINMM.DLL gesehen) ist, dass beim erneuten Aufruf der Methode Start_Filename, nämlich während schon ein MP3 gespielt wird, dieses quasi "abgeschossen" wird.

Dazu habe ich keine Methode in der Quartz.DLL gefunden die ich aufrufen könnte und auch ein Aufruf der Stop-Methode bringt nur eine Unterbrechung des aktuell spielenden Files im Millisekunden Bereich bevor es unbeirrt weiterspielt.

Wie gesagt hatte ich auch schon mit der RSPMP3Player-DLL gearbeitet, die absolut identisch instanziiert und über fast identsiche Methodenaufrufe angesprochen wird, aber dort geht mir einfach das Shareware-PopUp auf den Geist. Da es bei dieser DLL auch problemlos mit dem oben beschriebenen "abschiessen" des aktuell spielenden MP3s funktioniert, gehe ich einfach davon aus, dass die Quartz.DLL etwas nicht hat, was ich brauch, oder das ich was übersehen habe.

Falls es von Interesse ist, hier der LINK zu RSP MP3Player.dll

Trotzdem THX und Greeds Rando
 
OK weg von der Quartz DLL nun ein neues Problem! Ich habe den Code auf die WINMM.DLL umgestellt um mit mciSendString-Kommandos arbeiten zu können. Das sieht dann so aus:

Code:
using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Windows.Forms; 
using System.Threading;
using System.Runtime.InteropServices;

public class MP3_View : Chip_View{
	[DllImport("winmm.dll")]
	private static extern long mciSendString(string lpstrCommand, StringBuilder lpstrReturnString, int uReturnLength, int hwndCallback); 
	
	private String CommandString=null;

	public MP3_View()
	{
	assembly_name=Application.StartupPath+"\\"+"MP3_Chip.exe";
	SetPrimarySlot("MP3-File");
	Text="MP3_Pad";
	Size=new Size(100,100);
    }

    public override void CreateGUI(){
	gui=new Border3DLabel();
	((Border3DLabel)gui).Text="MP3 Player";
	((Border3DLabel)gui).TextAlign=ContentAlignment.BottomCenter;
	((Border3DLabel)gui).Image = 
	    Image.FromFile("C:\\images\\"+"speaker2.png");
	((Border3DLabel)gui).ImageAlign=ContentAlignment.TopCenter;
	Controls.Add(gui);
	((Border3DLabel)gui).BorderStyle=BorderStyle.None;
	((Border3DLabel)gui).Dock=DockStyle.Fill;
	((Border3DLabel)gui).MouseDown += 
	    new MouseEventHandler(MouseDown_CallBack);
	((Border3DLabel)gui).AllowDrop=true;
	MouseMove += new MouseEventHandler(MouseMove_CallBack);
	MouseUp += new MouseEventHandler(MouseUp_CallBack);
    }

    public override void ChangeBorder(){
	if(FormBorderStyle==FormBorderStyle.None){
	    FormBorderStyle=FormBorderStyle.SizableToolWindow;
	    ((Border3DLabel)gui).drawborder=false;
	    frame_menuitem.Checked=true;
	}else{
	    FormBorderStyle=FormBorderStyle.None;
	    ((Border3DLabel)gui).drawborder=true;
	    frame_menuitem.Checked=false;
	}
    }
    
	
    
	public override void UpdateView(String slotname, String value)
	{
		if(slotname=="MP3-File")
		Start_Filename(value);
	}

	private void Start_Filename(String value)
	{
		try
		{
			((Label)gui).Text=value;
			Set_Title(value);
			CommandString = "close Mp3File";
			mciSendString(CommandString,null,0,0);
			CommandString = "open " + "\"" + value + "\"" + " type MPEGVideo alias Mp3File";
			mciSendString(CommandString,null,0,0);
			CommandString = "play Mp3File";
			mciSendString(CommandString,null,0,0); 
		}
		catch(Exception){MessageBox.Show("No such file!");}
	}
	
	protected void Set_Title(String value)
	{
		this.Text=value;
	}

	public override void CreateMenu()
	{
		base.CreateMenu();
		AddMenuItem("-");
		AddMenuItemWithHandler("Pause");
		AddMenuItemWithHandler("Resume");
		AddMenuItemWithHandler("Stop");
	}
    
	public override void HandleMenuEvent(Object sender,EventArgs e)
	{
		MenuItem item=(MenuItem)sender;
		switch(item.Text)
		{
			case "Pause":
				Cursor.Current = Cursors.WaitCursor;
				CommandString = "pause Mp3File";
				mciSendString(CommandString,null,0,0); 
				Cursor.Current = Cursors.Default;
				break;
			case "Resume":
				Cursor.Current = Cursors.WaitCursor;
				CommandString = "resume Mp3File";
				mciSendString(CommandString,null,0,0); 
				Cursor.Current = Cursors.Default;
				break;
			case "Stop":
				CommandString = "close Mp3File";
				mciSendString(CommandString,null,0,0);
				break;
			default:
				base.HandleMenuEvent(sender, e);
				break;
		}
	}

	public static Chip_View CreateInstance(){
	MP3_View view= new MP3_View();
	view.model= new MP3_Model(view);   
	return view;
    }
    
    [STAThread]
    public static void Main(){
	Chip_View view= CreateInstance();
	Application.Run(view);
    }
}

Jetzt passiert beim Öffnen einer MP3 Datei und auch beim Öffnen einer weiteren Datei genau dass was ich haben will: Datei 1 (die aktive) wird abgebrochen und durch die neue Datei 2 ersetzt und abgespielt.

Jetzt ist der Ärger aber bei den Case-Statements. Diese Kommandos (pause, resume und stop) werden dann einfach ignoriert.

Weiss dazu jemand Rat?

(Wie zuvor, Code-Tags. Alex)
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück