Why is the MediaElement not playing a MediaStreamSource (in SilverLight)? - c#

When I try to stream sound from my microphone, I need to get it through a MediaStreamSource.
Therefore I first need to implement a MediaStreamSource for the pcm waveformat I get from my Microphone. There are at least two methods I think I need to implement. At first
protected override void OpenMediaAsync() {
// Create description
Dictionary<MediaStreamAttributeKeys, string> streamAttributes = new Dictionary<MediaStreamAttributeKeys, string>();
streamAttributes[MediaStreamAttributeKeys.CodecPrivateData] = output.CodecPrivateData;
audioDesc = new MediaStreamDescription(MediaStreamType.Audio, streamAttributes);
// register stream
Dictionary<MediaSourceAttributesKeys, string> sourceAttributes = new Dictionary<MediaSourceAttributesKeys, string>();
List<MediaStreamDescription> availableStreams = new List<MediaStreamDescription>();
availableStreams.Add(audioDesc);
sourceAttributes[MediaSourceAttributesKeys.Duration] = TimeSpan.FromMinutes(0).Ticks.ToString(); // whatever I put here I get the same result.
sourceAttributes[MediaSourceAttributesKeys.CanSeek] = false.ToString();
ReportOpenMediaCompleted(sourceAttributes, availableStreams);
}
This works very well. My CodecPrivateData is '01000100401F0000803E0000020010000000' (PCM 1ch 16Bits 8kHz). This method gets called by setting the source as here:
WaveMediaStreamSource WaveStream = new WaveMediaStreamSource(output);
mediaElement.SetSource(WaveStream);
mediaElement.Play();
After Play() absoultely nothing happens. I would suggest the mediaElement should call at least once the method GetSampleAsync() of the MediaStreamSource. But it doesn't. I've noticed that the MediaElement doesn't make any call to the MediaStreamSource anymore.
While OpenMediaAsync the mediaElement.CurrentState is Opening. After that it turns to Playing but it doesn't play. And then it do not change anymore and remains Playing.
Any Ideas?

To get to the bottom of this you need to check MediaElement.CurrentState - it will tell you at which step of the interaction with the MediaStreamSource the MediaElement is stuck. This in turn will tell which of your MediaStreamSource methods should be impemented differently...
For a comprehensive walkthrough including essential information on the buffering part see http://msdn.microsoft.com/en-us/library/hh180779%28v=vs.95%29.aspx

Some things to try...
Try setting CanSeek to "0" and try a duration greater than zero, any hard coded value is fine to at least try to get it working. Also double check your CodecPrivateData string and make sure it's correct.
You also may want to try dropping in the Mp3MediaStreamSource from the ManagedMediaHelpers project and get that working first to make sure everything else in your app is set up properly then switch back to your custom MediaStreamSource.

When developing a mediaElement for Windows Phone (WP7.5 and WP8), for a reason that is completely beyond me, the debugger will not break on any breakpoints in the GetSampleAsync callback, the first time the callback is called !
The debugger will break the next time the breakpoint(s) will be reached. Try replacing your GetSampleAsync with this:
protected override void GetSampleAsync(MediaStreamType mediaStreamType)
{
System.Diagnostics.Debug.WriteLine("Yay!");
MediaStreamSample msSamp = new MediaStreamSample(
_videoDesc, _frameStream, _frameStreamOffset,
_frameBufferSize, _currentTime, _emptySampleDict);
ReportGetSampleCompleted(msSamp);
}

Related

C#, No video, audio only, VLC using multiple forms, Black Screen?

Can someone please tell me whey I am getting a black screen with no video, only sound?
private void screen1btnPlay_Click(object sender, EventArgs e)
{
ScreenOne playScreen1 = new ScreenOne();
playScreen1.PlayScreenOne();
}
... and the other form is like this:
public partial class ScreenOne : Form
{
public ScreenOne()
{
InitializeComponent();
}
public void PlayScreenOne()
{
axVLCPlugin21.playlist.add("file:///" + #"Filepath", null);
axVLCPlugin21.playlist.play();
}
}
Sound works fine, but no video. All the properties of the VLC are left to default, is there something I need to change when using this plugin across multiple forms? Anyone know what's wrong?
Update:: I rebuilt the program in WPF and I am having the same problem. When I have a button on the second form (same form as player) it works fine, as soon as I call it from the main form, sound only. ugh!
I dont know but i can give some solution suggestions,
Make sure the VLC program is installed as 32-bit. I dont know, I've solved a problem that way.
I think high probabilty your problem is based on about "C:\Program Files (x86)\VideoLAN\VLC\plugins" Check your plugins. maybe your audio_filter, audio_mixer, audio_output plugins are missing.
you can remove Vlc, then download and install last VLC 32 bit.
I think that will solve your problem. Dont forget AxAXVLC works with vlc plugins.
I figured out my problem on my own!
When I was creating this instance,
ScreenOne playScreen1 = new ScreenOne();
I was actually creating a redundant instance of what I was trying to do, I'm not sure if that's the right way to put it but I basically already had an instance of the second form and was making another separate instance of the form that was named differently.
I already had in my code to open the second form
Screen2 Screen2 = new Screen2();
private void openScreen2Button_Click(object sender, EventArgs e)
{
Screen2.Show();
}
Then later was doing this which is WRONG, I was adding playscreen1 when I should still have been using Screen2.
Screen2 playScreen1 = new Screen2();
playScreen1.PlayScreenOne();
So when I wanted to use the method to play the media player on the second form from the first one, I just needed to use the same instance of Screen2 that I had created to open the form to begin with instead of created a new instance for what method I wanted to use.
IDK if my explanation makes sense, or maybe its basics to most people (I'm a noob), but if anyone comes across this problem, message me and I'll try to help.
o7

In coded ui how do you correctly retrieve a browser window that contains an embedded Adobe PDF reader in browser

I'am running across this issue when I'm debugging or running my coded UI automation project, where i get the exception labeled "{"COM object that has been separated from its underlying RCW cannot be used." System.Exception {System.Runtime.InteropServices.InvalidComObjectException}" everytime i come from a browser window that contains a pdf reader embedded in it. This happens every time I retrieve the window and try to click back. It barfs when i perform the back method on it. I've tried different things but none has worked including the playback wait.
var hereIsmypdf = ReturnPDFDoc();
public BrowserWindow ReturnPDFDoc()
{
Playback.Wait(1000);
var myPdFdoc = GlobalVariables.Browser;
return myPdFdoc;
}
hereIsmypdf.Back();
The only way i was able to get around this issue was not to use the BrowserWindow class. I ended up using the WinWindow class and just getting the tab of the window from it. The BrowserWindow class seemed to trigger the exception "COM object that has been separated from its underlying RCW cannot be used." System.Exception {System.Runtime.InteropServices.InvalidComObjectException}" everytime i tried to retrieve it. I hope this helps someone one or maybe someone has a better way to handle this issue.
For the people that voted my question down, i really did try to figure it out. Sorry i wasnt clear about what i was asking the community or couldn't properly articulate what this pain was. I'm sure someone probably is going through the same pain i did and having a hard time articulating whats going on.
Here is my code on what i ended up doing
public WinTabPage ReturnPDFDoc()
{
WinWindow Wnd = new WinWindow();
Wnd.SearchProperties[BrowserWindow.PropertyNames.ClassName] = "IEFrame";
WinTabList tabRoWlist = new WinTabList(Wnd);
tabRoWlist.SearchProperties[WinTabPage.PropertyNames.Name] = "Tab Row";
WinTabPage myTab = new WinTabPage(tabRoWlist);
myTab.SearchConfigurations.Add(SearchConfiguration.AlwaysSearch);
myTab.SearchProperties[WinTabPage.PropertyNames.Name] = "something";
//UITestControlCollection windows = newWin.FindMatchingControls();
return myTab;
}

MediaPlayerLauncher on WP7 - how to resume previously playing media?

I'm using a MediaPlayerLauncher to show movietrailers in my WP7 application, like this:
MediaPlayerLauncher mpl = new MediaPlayerLauncher();
mpl.Media = new Uri(trailerUrl, UriKind.Absolute);
mpl.Controls = MediaPlaybackControls.All;
mpl.Show();
This works just fine, except one thing: if the user is already listening to music in the background, and launch a trailer, the music is not resumed after the trailer is done playing (or if the user closes the video).
Does anyone know how i can resume the previously playing music/media, if even possible?
Local media playing through XNA or a 'background audio agent'?
When you play media in WP7 / WP8, the OS audio context is taken, and the original context is lost. If the audio was launched from an external application, then you cannot resume at all. If the previous media was launched from within your application, then you could store the meta-data and re-play once your trailer is finished. The media would, of course, then begin playing from the start, rather than where the user left off. Unfortunately XNA does not allow you to seek within a given piece of media; however you can seek within an 'audio agent' instance of 'BackgroundAudioPlayer' by setting player.Position. It's also worth looking at the MediaHistory API:
var nowPlaying = Microsoft.Devices.MediaHistory.Instance.NowPlaying;
Figured it out. Calling MediaPlayer.Resume() right after show() solves the issue:
mpl.Media = new Uri(trailerurl, UriKind.Absolute);
mpl.Controls = MediaPlaybackControls.All;
mpl.Show();
MediaPlayer.Resume();
However, i would still like to know how to resume radio and spotify!

I must be a heretic for wanting a C# browser with both NewWindow2 and GetElementsByTagName

You can't have your cake and eat it too, apparently.
I'm currently using the System.Windows.Forms.WebBrowser in my application. The program currently depends on using the GetElementsByTagName function. I use it to gather up all the elements of a certain type (either "input"s or "textarea"s), so I can sort through them and return the value of a specific one. This is the code for that function (my WebBrowser is named web1):
// returns the value from a element.
public String FetchValue(String strTagType, String strName)
{
HtmlElementCollection elems;
HtmlDocument page = web1.Document.Window.Frames[1].Document;
elems = page.GetElementsByTagName(strTagType);
foreach (HtmlElement elem in elems)
{
if (elem.GetAttribute("name") == strName ||
elem.GetAttribute("ref") == strName)
{
if (elem.GetAttribute("value") != null)
{
return elem.GetAttribute("value");
}
}
}
return null;
}
(points to note: the webpage I need to pull from is in a frame, and depending on circumstances, the element's identifying name will be either in the name or the ref attribute)
All of that works like a dream with the System.Windows.Forms.WebBrowser.
But what it is unable to do, is redirect the opening of a new window to remain in the application. Anything that opens in a new window shoots to the user's default browser, thus losing the session. This functionality can be easily fixed with the NewWindow2 event, which System.Windows.Forms.WebBrowser doesn't have.
Now forgive me for being stunned at its absence. I have but recently ditched VB6 and moved on to C# (yes VB6, apparently I am employed under a rock), and in VB6, the WebBrowser possessed both the GetElementsByTagName function and the NewWindow2 event.
The AxSHDocVw.WebBrowser has a NewWindow2 event. It would be more than happy to help me route my new windows to where I need them. The code to do this in THAT WebBrowser is (frmNewWindow being a simple form containing only another WebBrowser called web2 (Dock set to Fill)):
private void web1_NewWindow2(
object sender,
AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)
{
frmNewWindow frmNW = new frmNewWindow();
e.ppDisp = frmNW.web2.Application;
frmNW.web2.RegisterAsBrowser = true;
frmNW.Visible = true;
}
I am unable to produce on my own a way to replicate that function with the underwhelming regular NewWindow event.
I am also unable to figure out how to replicate the FetchValue function I detailed above using the AxSHDocVw.WebBrowser. It appears to go about things in a totally different way and all my knowledge of how to do things is useless.
I know I'm a sick, twisted man for this bizarre fantasy of using these two things in a single application. But can you find it in your heart to help this foolish idealist?
I could no longer rely on the workaround, and had to abandon System.Windows.Forms.WebBrowser. I needed NewWindow2.
I eventually figured out how to accomplish what I needed with the AxWebBrowser. My original post was asking for either a solution for NewWindow2 on the System.Windows.Forms.WebBrowser, or an AxWebBrowser replacement for .GetElementsByTagName. The replacement requires about 4x as much code, but gets the job done. I thought it would be prudent to post my solution, for later Googlers with the same quandary. (also in case there's a better way to have done this)
IHTMLDocument2 webpage = (IHTMLDocument2)webbrowser.Document;
IHTMLFramesCollection2 allframes = webpage.frames;
IHTMLWindow2 targetframe = (IHTMLWindow2)allframes.item("name of target frame");
webpage = (IHTMLDocument2)targetframe.document;
IHTMLElementCollection elements = webpage.all.tags("target tagtype");
foreach (IHTMLElement element in elements)
{
if (elem.getAttribute("name") == strTargetElementName)
{
return element.getAttribute("value");
}
}
The webbrowser.Document is cast into an IHTMLDocument2, then the IHTMLDocument2's frames are put into a IHTMLFramesCollection2, then I cast the specific desired frame into an IHTMLWindow2 (you can choose frame by index # or name), then I cast the frame's .Document member into an IHTMLDocument2 (the originally used one, for convenience sake). From there, the IHTMLDocument2's .all.tags() method is functionally identical to the old WebBrowser.Document.GetElementsByTagName() method, except it requires an IHTMLElementCollection versus an HTMLElementCollection. Then, you can foreach the collection, the individual elements needing to be IHTMLElement, and use .getAttribute to retrieve the attributes. Note that the g is lowercase.
The WebBrowser control can handle the NewWindow event so that new popup windows will be opened in the WebBrowser.
private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
{
// navigate current window to the url
webBrowser1.Navigate(webBrowser1.StatusText);
// cancel the new window opening
e.Cancel = true;
}
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/361b6655-3145-4371-b92c-051c223518f2/
The only solution to this I have seen was a good few years ago now, called csExWb2, now on Google code here.
It gives you an ExWebBrowser control, but with full-on access to all the interfaces and events offered by IE. I used it to get deep and dirty control of elements in a winforms-hosted html editor.
It may be a bit of a leap jumping straight into that, mind.

Pausing and resuming mp3 with WMPLib and C#

I'm working on a simple mp3 player project with C# and the WMPLib library. The idea is to make it controllable with a PIC component, to control media playing in the PC from "anywhere" in my house (yes, this is a college project).
The problem: I can't get the WindowsMediaPlayer.controls.play() method to resume a paused playback. How should I do it?
I've already tried to save and set the WindowsMediaPlayer.controls.currentPosition property, but it doesn't work.
PS:
The same problem: http://social.msdn.microsoft.com/Forums/en-US/windowspro-audiodevelopment/thread/770d22fc-7ef1-475e-a699-b60e2282a7c7/
Different problem: pause and resume Windows Media Player in C#
Thanks in advance
EDIT: WindowsMediaPlayer.controls.currentPosition works fo setting the position, but not for getting it:
double time = Player.controls.currentPosition; //Returns 0 always
Player.controls.currentPosition = time; //Works fine, makes music jump to time seconds
...
double time = Player.controls.currentPosition; //return always 0 for you, because you pause first and after get the value
Player.controls.pause();
Player.controls.currentPosition = time;
Player.controls.play();
You can get currentposition by converting it to string for example:
label1.text = convert.tostring(Player.controls.currentPosition);
I've used a label to show you the exactly currentPosition value.
Regards

Categories