Archive

Posts Tagged ‘Silverlight’

HowTo: Use Silverlight-enabled website in Microsoft Edge Chromium

Let’s see how we can use a Silverlight-enabled website in Microsoft Edge Chromium

1) When we visit the site we’ll see a “Click now to install” button that used to download and install Silverlight, but that recently stopped working. Even before though, it wouldn’t work with Edge Chromium after installation, but show everytime the same download prompt

Screenshot (1)

2) Press “…” button at top-right and select “Settings”

Screenshot (2)

3) Pick Appearance at the left sidebar and scroll down on the right to “Internet Explrorer mode button”. If the switch to turn it on is disabled (grayed out), then press the link “allow sites to be reloaded in Internet Explorer mode”

Screenshot (5)

4) This will take you to edge://settings/defaultBrowser, where you should change “Allow sites to be reloaded in Internet Explorer mode” from “Default” to “Allow”. After that press the “Restart” button shown.

Screenshot (9)

5) Now if you go back to Appearance, you can turn on the “Internet Explorer mode button” option

Screenshot (10)

6) Now if you go back to the website, you’ll see a button at top-right allowing you to open the page in Internet Explorer mode. The same action is also available on the “…” menu, but having it as a button too can prove handy.

Screenshot (12)

7) If Microsoft hadn’t broken the direct Silverlight download links, then from this point you would be set and could use the respective website by first installing the Silverlight ActiveX control. But instead you’ll get:

Screenshot (17)

8) Luckily archive.org has cached the last Silverlight releases (you can also check them on virustotal.com after downloading if you wish) and hope they will keep them, since they’re the most trustworthy alternative source for those installers (after Microsoft of course). Ignore the “Developer” versions and just get the x86 (Silverlight.exe) or x64 (Silverlight_x64.exe) version, depending on your Windows installation

Screenshot (24)

9) Since they keep various versions archived, make sure you get the latest available one from there.

Screenshot (22)

10) After the download completes you will be able to run the downloaded installer

Screenshot (23)

11) When the installer starts, uncheck the options “Make Bing my search engine” and “Make MSN my homepage” if you don’t wish to do those actions. Then press Install now and after it downloads and installs, select “Enable Microsoft Update” (as recommended) and press Next and then Close.

Screenshot (26)

Screenshot (27)Screenshot (28)

Screenshot (29)

12) Now if you visit the Silverlight-based website again you will see the Download Silverlight prompt, but if you press the “IE mode” button on the Edge toolbar (or do the same action from the “…” menu), you’ll see the Silverlight application loading (could show some loading progress animation there or some percentage – depends on the application).

Screenshot (30)

13) You will see a popup open up where you can select that Edge should remember the current url and open it in Internet Explorer mode next time too (if you press Manage on that popup you can see those sites which are remembered for 30 days). Those sites can be managed at edge://settings/defaultBrowser

Screenshot (34)

14) after that the website opens up in Internet Explorer mode with a small warning bar at the top that you can close with the [x] button on its right

Screenshot (31)

15) And presto, you can see below ClipFlair Studio (http://studio.clipflair.net) working fine in Microsoft Edge Chromium via Internet Explorer mode and the Silverlight ActiveX Control.

Wish Microsoft wouldn’t make lives of users that hard. Not all sites are backed by multi-million dollar companies to be rewritten from scratch with HTML-based technology that still strives to support what Silverlight was offering with ease (btw, if you’d care to sponsor Clipflair Studio’s future evolutions, can donate via the respective button at https://github.com/zoomicon/clipflair)

Screenshot (32)

In the case of ClipFlair, you’ll need to do the final steps of this process for these URLs:

http://studio.clipflair.net

http://gallery.clipflair.net/activity

http://gallery.clipflair.net/video

http://gallery.clipflair.net/photo

Fix: Enable Silverlight & other NPAPI plugins at Chrome web browser

Below I’m elaborating a bit more my related tweet:

 

Showing below the easiest of the suggested solutions that I found in this page

 

At Chrome’s address bar you type:

chrome://flags/#enable-npapi

and press the ENTER key on the keyboard

image

Then you should see a page Chrome generates to change some of its internal settings. When NPAPI is disabled the respective entry should appear in grey background like below.

image

Press Enable at the setting “Enable NPAPI Mac, Windows”

After enabling NPAPI the page should look like this (with the respective setting in white background):

image

After enabling the NPAPI option, close the Chrome webbrowser and reopen it.

 

You can then test if Silverlight is working by visiting for example

http://studio.clipflair.net (ClipFlair Studio Foreign language learning application) or http://zoomicon.com/amnesiaofwho (Amnesia of Who memory game)

 

Btw, Chrome also is available as a Windows 8 app, in which mode it probably doesn’t support plugins at all, so if you’re running it on Windows 8 and see it always full screen inside a scrolling container, use the Chrome menu from the top-right of its window and select the option there to switch to the desktop version of Chrome instead (should say "Relaunch Chrome in desktop mode")

HowTo: Open page from Internet Explorer (Metro) app into desktop IE

The Windows 8/8.1 app version of Internet Explorer is also known as IE Metro because of the “Metro” codename (inspired by navigation signs in public transport] of the Modern UI design language promoted by Microsoft).

However that version isn’t the full Internet Explorer, in that it is unfortunately not supporting extensibility via plugins in the form of ActiveX controls as the classic (desktop version) of IE. It is only embedding the Flash player engine directly in its codebase, but not Microsoft’s own Rich Internet Application (RIA) rendering engine aka Silverlight, nor Unity or other VRML/X3D, QuickTime/QuickTimeVR etc. plugins.

Browser pages cannot detect the difference between running IE on the desktop or as an app, there is however a workarround for webpage authors or webadmins to force the app version of IE to show a prompt to the user that allows the opening of a page in the desktop version of Internet Explorer. There is also a way for System Administrators to set specific sites to open in the desktop version of IE without the user seeing such prompt.

At https://msdn.microsoft.com/en-us/library/ie/hh968248.aspx, Microsoft mentions:

As a web developer, you can enable the requiresActiveX feature switch either by using this HTTP header:

X-UA-Compatible: requiresActiveX=true

Or by using this meta element on each affected webpage:

<meta http-equiv="X-UA-Compatible" content="requiresActiveX=true"/>

 

I just added the meta tag inside the <head>…</head> block of the Amnesia of Who web version that uses Silverlight and here is how it shows in the IE Metro version (note that Silverlight IS installed in that Windows 8.1 machine, it’s just that it’s not available in that browser, that’s why the Silverlight installation prompt is also shown):

image

When the user presses the default button “Open on the desktop”, the OS switches to classic desktop mode and shows an Internet Explorer window with the Silverlight application starting fine (or if Silverlight is not installed it will prompt and allow the user to install it – note that Silverlight ActiveX control’s installation doesn’t need administrator permissions since that installation doesn’t affect other users, nor requires any elevated rights in the system to work).

image

 

I hope that Microsoft, apart from keeping on supporting this workarround, will do a clever move this time and embed Silverlight too (apart from the Flash engine that was in IE Metro) in the Spartan browser that it prepares as the Windows 10 default touch browser. And why not, provide some extensibility method for it, since HTML5 cannot become a huge, impossible to implement beast, that covers every future conceived functionality for the web.

Gotcha: MediaElement Source=null releases stream, SetSource(null) fails

This is my contribution to:

http://stackoverflow.com/questions/19294258/forcing-mediaelement-to-release-stream-after-playback/27436323

If you use MediaElement, make sure you don’t get bitten by this one: http://msdn.microsoft.com/en-us/library/cc626563(v=vs.95).aspx

ArgumentNullException – The mediaStreamSource is null.

After calling this method, MediaElement.Source returns null. If this is called and MediaElement.Source is set, the last operation wins.

If a MediaElement is removed from the UI tree while is has an opened MediaStreamSource, subsequent calls to SetSource may be ignored. To ensure featureSetSource calls will work, set the Source property to null before detaching the MediaElement from the UI tree.

naturally one would expect, if they only use SetSource(somestream) to use SetSource(null) to release the resources. Nope, they thought "better", you have to use Source=null instead to release resources and SetSource(null) throws ArgumentNullException

that is what I call a design bug (breaks the rule of "least expected" behavior and causes bugs that bite you at runtime only [unless somebody has made a static analysis rule to catch such a thing – would need metadata of course that some argument can’t be null, like in Code Contracts])

I managed to introduce this bug while refactoring some code in ClipFlair Studio‘s AudioRecorder control the other day 😦

Note that you can’t use at MediaElement something like Source = stream to open a Stream, since that is a Uri property (not an Object property to also accept Stream) and you have to use SetSource(stream) instead, so you’d also expect to be able to use SetSource(null) to release the resources.

Update: Fixed this in AudioRecorderView class (uses MVVM pattern) of AudioRecorderControl, at Audio property’s "set" accessor it needed the following null-guarding pattern:

if (mediaStreamSource != null) 

  player.SetSource(mediaStreamSource); 
      //must set the source once, not every time we play the same audio, 
      //else with Mp3MediaSource it will throw DRM error

else

   player.Source = null;

Fix: Allow rewind of Mp3MediaStreamSource back to start

My comment at:

https://github.com/loarabia/ManagedMediaHelpers/issues/16

While trying to use Mp3MediaSource at ClipFlair Studio’s AudioRecorder control (http://clipflair.codeplex.com), I noticed that when I was doing Stop() at MediaElement and then Play() it kept on playing from where it was before at Mp3MediaStreamSource

So I did the following fix:

 

1) added these fields

    /// <summary>
    /// The first known frame (for rewind)
    /// </summary>     
    private MpegFrame firstFrame;

    /// <summary>
    /// The first audio stream position (for rewind)
    /// </summary>
    private long firstAudioStreamPosition;

 

2) added to the end of ReadPastId3v2TagsCallback:

this.firstFrame = mpegLayer3Frame; //keeping the 1st frame position for rewinding
this.firstAudioStreamPosition = audioStream.Position;

 

3) changed SeekAsync:

    /// <summary>
    /// <para>
    /// Only supporting seeking back to start of the stream 
/// (e.g. when doing MediaElement.Stop()). /// </para> /// <para> /// In a fuller MediaStreamSource, the logic here would be to actually seek to /// the correct mpeg frame matching the seekToTime passed in. /// </para> /// </summary> /// <param name="seekToTime"> /// The time to seek to (in 100-nanosecond units [hns]) /// </param> protected override void SeekAsync(long seekToTime) { /* if (seekToTime > this.trackDuration.TotalMilliseconds * 10) { throw new InvalidOperationException(
"The seek position is beyond the length of the stream"); } */ if (seekToTime != 0) //only supporting rewinding back to start throw new InvalidOperationException(
"Only supporting seeking back to start of the stream"); else { this.currentFrame = firstFrame; this.currentFrameStartPosition = MpegFrame.FrameHeaderSize; this.audioStream.Position = firstAudioStreamPosition; } this.ReportSeekCompleted(seekToTime); }

 

note that I changed the documentation for that method to say that time passed to it is in 100 ns units, not in ns units (according to WaveMediaStreamSource code that I found, unless that one has it wrong)

Gotcha: MediaElement must be in visual tree for MediaOpened, MediaEnded to be fired

At ClipFlair’s AudioRecorderControl (used in Captions/Revoicing component of ClipFlair Studio), I use the following code to initialize a MediaElement to use for playback.

After a long time a found out that if the MediaElement is not in the visual tree (for example defined in XAML, or defined in code and then added to the visual tree), then it will not always fire MediaOpened and MediaEnded events, which are crucial if you want to have a two-state Play/Stop button (a ToggleButton).

 

public MediaElement Player
{   get { return player; }   
set {    
if (player != null) {      
player.MediaOpened -= MediaElement_MediaOpened;
player.MediaEnded -= MediaElement_MediaEnded;    
}    

player = value;


    
if (player != null)  {      
player.MediaOpened += MediaElement_MediaOpened;
        player.MediaEnded += MediaElement_MediaEnded;

       player.AutoPlay = false;
       player.PlaybackRate = 1.0;
       player.Balance = 0;
       Volume = DEFAULT_VOLUME;  
  }
  } }

 

protected void MediaElement_MediaOpened(object sender, RoutedEventArgs e)
{   
try   {    
//player.Position = TimeSpan.Zero;     
player.Stop(); //this stops current playback (if any) and rewinds
    player.Play();  
}   catch (Exception ex)   {    
PlayCommandUncheck(); //depress playback toggle button
//don't talk to ToggleButton directly    
Status = MSG_PLAY_FAILED + ex.Message;  
} }
 

protected void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
  PlayCommandUncheck(); //depress play button to stop playback
//don't talk to ToggleButton directly }

Gotcha: MediaElement AutoPlay faster than doing Play at MediaOpened

Just added the following comment to: https://github.com/loarabia/ManagedMediaHelpers/issues/15

Managed Media Helpers contains the very useful Mp3MediaSource class for .NET / Silverlight / Windows Phone.

Added compile-time SWITCHES and respective code to Silverlight demo code for PRELOAD (into memory stream) and AUTOPLAY (this was a bit tricky, need to call Play at MediaOpened event, not right after setting the source to the MediaElement).

Also seems to be 2-3 sec slower than AutoPlay (!) irrespective of using PRELOAD. Maybe it is faster to set the source again every time you want to play and just keep AutoPlay=true

Update: had a bug at the following code, obviously you first must set the MediaOpened event handler, then set the Source to the MediaPlayer. Also, one could set that handler once at the InitializeComponent method.

 

//———————————————————————–
// <copyright file="Page.xaml.cs" company="Larry Olson">
// (c) Copyright Larry Olson.
// This source is subject to the Microsoft Public License (Ms-PL)
// See http://code.msdn.microsoft.com/ManagedMediaHelpers/Project/License.aspx
// All other rights reserved.
// </copyright>
//
// Edited by George Birbilis (http://zoomicon.com)
//———————————————————————–

#define AUTOPLAY
//#define PRELOAD

namespace Mp3MediaStreamSourceDemo
{
  using Media;
  using System;
  using System.IO;
  using System.Windows;
  using System.Windows.Controls;

    /// <summary>
    /// A Page of a Silvelight Application.
    /// </summary>
    public partial class Page : UserControl
    {
        /// <summary>
        /// Initializes a new instance of the Page class.
        /// </summary>
        public Page()
        {
            InitializeComponent();

            me.Volume = 1.0; //set max volume
           
            #if !AUTOPLAY
            me.AutoPlay = false;

             me.MediaOpened += (s, e) =>
            {
                //me.Position = TimeSpan.Zero;
                me.Stop(); //this stops current playback (if any) and rewinds back to start
                //me.PlaybackRate = 1.0;
                try
                {
                    me.Play();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            };  
            #endif
        }

        /// <summary>
        /// Event handler for the Button on the Page.
        /// </summary>
        /// <param name="sender">
        /// The button which was clicked.
        /// </param>
        /// <param name="e">
        /// The state when this event was generated.
        /// </param>
        private void OpenMedia(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.ShowDialog();

            Stream data = ofd.File.OpenRead();

            #if PRELOAD
            Stream m = new MemoryStream((int)ofd.File.Length);
            data.CopyTo(m);
            m.Position = 0;
            data = m;
            #endif

 

             Mp3MediaStreamSource mediaSource = new Mp3MediaStreamSource(data);     
            me.SetSource(mediaSource);
        }
    }
}

Fix: Hypelinks not clickable in RichTextBox under Silverlight

Just fixed a nasty bug in ClipFlair Studio (http://studio.clipflair.net), where one couldn’t click hyperlinks in the Text component when set at ReadOnly mode. In that mode hyperlinks should open up new web pages (in Edit mode you can edit/remove them only of course), but instead when clicked they would show something like a focus rectangle (which they normally never show).

image

The situation was hard to debug since it wasn’t obvious what had caused the issue (it was working some time ago). I eventually found out that when the RichTextBox in Silverlight (may occur in WPF and WinRT too, haven’t tried) has a Transparent background, then Hyperlinks in it let MouseLeftButtonDown events pass through, so OnMouseLeftButtonDown will fire at their visual parent (or other visual ancestor) if no component in the visual chain marks the event as handled (such events bubble up towards the top of the visual hierarchy/containment chain).

This shouldn’t be much of a problem, if there wasn’t another issue, where if the ancestor called CaptureMouse in their OnMouseLeftButtonDown overriden method (from Control class), which is usual in mouse dragging code (in my case it was a FloatingWindow [TextWindow] that was the visual ancestor of RichTextBox), the hyperlink fails to fire when clicked and shows that weird solid-line border arround it instead.

The fix was easy once I knew what was happening, I attached a MouseLeftButtonDown event handler to the RichTextBox (if one was subclassing it [assuming it allows to do so] they could also have opted to add an overriden OnMouseLeftButtonDown method) that sets Handled property of the event parameter to true to consume it. The fix is available at CodePlex.

One can verify that the fix works now by downloading a sample ClipFlair Activity from https://www.dropbox.com/s/1zr36190xb0m6vk/Test_Text_URLs.clipflair and opening it in ClipFlair Studio. Can also download and build/run the source code of the previous broken version 1faaa8b35749 and test with that save activity file to see that the URLs didn’t open before when clicked but showed a rectangle arround them intead.

image

HowTo: use PivotViewer in WPF

PivotViewer is an impressive Silverlight control (see my usage at http://gallery.clipflair.net), however Microsoft never released it for WPF.

One could work arround this by embedding Silverlight in their WPF app using the WebBrowser control and talking to it via the JavaScript Bridge of Silverlight, however they could also embed one of those HTML5 PivotViewer-compatible controls that have surfaced in recent years.

Apart from LobsterPot’s HTML5 PivotViewer and its older free version, for another HTML5 PivotViewer (and also a DeepZoom implementation for HTML5) you could host that comes from former SeaDragon team members at Microsoft and seems to work very well see:

http://seajax.github.io/

https://github.com/seajax/seajax/tree/master/v2/app/pivot

https://github.com/seajax/seajax/blob/master/v2/app/pivot/quickstart.html

https://github.com/seajax/seajax

Note that the WebBrowser control uses IE7 or something as HTML engine by default and you need some meta markup at the top of your HTML to tell it to use Edge mode – the latest IE engine that is installed)

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Gotcha: System.IO.GetInvalidPathChars result not guaranteed

at System.IO.Path.GetInvalidPathChars one reads:

The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names

note: can also call this method from non-trusted Silverlight app – not as Intellisense tooltip wrongly says in Visual Studio 2013 with Silverlight 5.1

I just found out about this the hard way (since DotNetZip library was failing at SelectFiles to open .zip files that it had before successfully saved with item filenames containing colons). So I had to update my ReplaceInvalidFileNameChars string extension method to also replace/remove invalid characters such as the colon, wildcard characters (* and ?) and double quote.

    public static string ReplaceInvalidFileNameChars(
this string s,
string replacement = "") { return Regex.Replace(s, "[" + Regex.Escape( Path.VolumeSeparatorChar + Path.DirectorySeparatorChar + Path.AltDirectorySeparatorChar + ":" + //added to cover Windows & Mac in case code is run on UNIX "\\" + //added for future platforms "/" + //same as previous one "<" + ">" + "|" + "\b" + "" + "\t" + //based on characters not allowed on Windows new string(Path.GetInvalidPathChars()) + //seems to miss *, ? and " "*" + "?" + "\"" ) + "]", replacement, //can even use a replacement string of any length RegexOptions.IgnoreCase); //not using System.IO.Path.InvalidPathChars (deprecated insecure API) }


Useful to know:

System.IO.Path.VolumeSeparatorChar

slash ("/") on UNIX, and a backslash ("\") on the Windows and Macintosh operating systems

 

System.IO.Path.DirectorySeparatorChar

slash ("/") on UNIX, and a backslash ("\") on the Windows and Macintosh operating systems

 

System.IO.Path.AltDirectorySeparatorChar

backslash (‘\’) on UNIX, and a slash (‘/’) on Windows and Macintosh operating systems

More info on illegal characters at various operating systems can be found at:

http://support.grouplogic.com/?p=1607

%d bloggers like this: