« Add-SPSolution : "Access Denied" Vicious Circle (SharePoint 2010) | Main | SharePoint People Picker: Override Validation Logic »
Tuesday
Sep152009

Audio file support in a SharePoint Document Library

Add an audio file into a SharePoint document library and try to open it. You will get the following message if you are using IE 8 (or previous version of IE):

 

If you upload audio files to a regular document library, SharePoint will sends back the file request as MIME Type of “text/html” (maybe text/plain) instead of “audio/wav” (or something similar audio type). For that reason, IE is not smart enough to detect the content is in fact an audio file to launch the appropriate application, perhaps Windows Media player (Google Chrome can actually detect it and play the audio file in-browser).

The solutions I can think of are the following:

Solution-1: Change your document library view to “Explorer View”, and it will basically detect any file type in your document library as if they were in your local machine. Keep note that it is actually running system commands and that might be unsafe.

Solution-2: Create an HttpModule to intercept requests to the SharePoint Web application, detect if an audio file has been request, then respond back with a MIME type “audio/wav” instead of “text/html”, and then let the browser detect the audio file and open its appropriate windows application.

Solution-3: Create a custom Field Type that uses a form-rendering control that figures out the URL of the audio and embeds a windows media player to play the audio when item is in “View Properties” mode. Then, make use of your new custom field type in your SharePoint document library.

Solution-4: Dynamically add “Play” Edit Control Block for audio items, and when clicked it navigates to a SharePoint application page that plays the audio in-browser Windows Media Player.

Solution-1 is slick and quick way of solving it, if users are willing to run system commands of course. Solution-2 is theoretically feasible. Effects are at the web application level, which makes it interesting, and worth looking at, as you can apply the same concept to other non-supported files in SharePoint Document libraries. Solution-3 sounds possible too. In fact I first started out this road, and realized it will need more effort and time than I expected it would (If possible I might give it a shot sometime, at least to explore the intrinsic involved in custom field types, RenderPattern elements and form-rendering controls). But, if you like the idea of having a “Play” ECB specifically added for audio files and let’s you play audios from your browser without opening other apps in your machine, then solution-4 is what you are looking for.

Here you find sample codes. Sample codes!!!! In other words, you have to clean it up on your own.

But anyways, the followings are the different components of solution-4:

  • Audio Library: A SharePoint document library containing audio files (ex: files with extension .wav)
  • Audio-Check Service: a SharePoint application Page used as a simple web service that can determine whether an item in SharePoint is an audio file or not. All it does is receive a SharePoint item URL, uses the Object Model to determine the extension of the file, then responses back a Boolean value in an XML format.
  • Content Editor Web Part: added on the same page as the List View Web Part of the audio library. It will contain JavaScript codes that uses SharePoint JavaScript Context object and XHR object to make Ajax calls to Audio-Check Service, determines whether or not a document is an audio file, and depending on the result decides to put the “Play” edit control block for only audio files.
  • Audio Player Page: a SharePoint application page that receives an audio file URL and plays audio on a page using embedded Windows Media Player.

Audio-Check Service

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Web;
   6: using Microsoft.SharePoint.WebControls;
   7: using Microsoft.SharePoint;
   8: namespace NaT.SharePoint.EditControlBlockAudioSupport.WebControls
   9: {
  10:     public class AudioCheckService : LayoutsPageBase
  11:     {
  12:         protected WindowsMediaPlayer _mediaPlayer;
  13:         protected override void OnLoad(EventArgs e)
  14:         {
  15:             base.OnLoad(e);
  16:  
  17:             string itemId = this.Request.QueryString["ItemID"];
  18:             string listId = this.Request.QueryString["ListID"];
  19:             string audioCheck = this.Request.QueryString["AudioCheck"];
  20:  
  21:             
  22:             if(audioCheck != null)
  23:             {
  24:                 SPList list = this.Web.Lists[new Guid(listId.Trim())];
  25:                 SPListItem item = list.GetItemById(Int32.Parse(itemId.Trim()));
  26:                 bool displayEditControlBlock = this.IsItemAnAudioFile(item);
  27:                 this.ResponseDecision(displayEditControlBlock);
  28:             }
  29:         }
  30:  
  31:         public bool IsItemAnAudioFile(SPListItem item)
  32:         {
  33:             return item.File != null && item.File.Name.EndsWith(".wav");
  34:         }
  35:  
  36:         public void ResponseDecision(bool decision)
  37:         {
  38:             this.Response.ClearHeaders();
  39:             this.Response.ClearContent();
  40:             this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
  41:             this.Response.AddHeader("Content-type", "text/xml");
  42:             this.Response.Write(@"<?xml version=""1.0"" encoding=""UTF-8"" ?>");
  43:             const string cmdPattern = @"<Command>{0}</Command>";
  44:             this.Response.Write(string.Format(cmdPattern, decision.ToString().ToLower()));
  45:             this.Response.End();
  46:         }
  47:     }
  48:     
  49: }

 

Audio Player Page

For playing back audio you can use <OBJECT /> HTML Tag for embedding Windows Media Player in your browser, it let’s you pass a URL as a parameter and streams it back for you.

<OBJECT 
id="{0}"
CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
type="application/x-oleobject" height="500px" width="500px">
<PARAM NAME="URL" VALUE="" />
<PARAM NAME="SendPlayStateChangeEvents" VALUE="True" />
<PARAM NAME="AutoStart" VALUE="true" />
<PARAM NAME="AnimationAtStart" VALUE="true" />
<PARAM NAME="ShowControls" VALUE="true" />
<PARAM NAME="ShowAudioControls" VALUE="true" />
<PARAM NAME="ShowTracker" VALUE="true" />
<PARAM NAME="EnableTracker" VALUE="true" />
<PARAM NAME="ShowStatusBar" VALUE="true" />
<PARAM NAME="ShowDisplay" VALUE="true" />
<PARAM NAME="AudioStream" VALUE="true" />
<PARAM NAME="ShowPositionControls" VALUE="true" />
<PARAM NAME="EnableFullScreenControls" VALUE="true" />
<PARAM name="uiMode" value="none" />
<PARAM name="PlayCount" value="1" />
<PARAM name="FileName" value="{1}" />
</OBJECT>

Create a Web Control that uses the <OBJECT /> Tag. I would prefer putting the Object Tag format in a different embedded file have that loaded in your Window Media Player Web Control:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Web;
   6: using System.Web.UI;
   7: using System.Web.UI.WebControls;
   8:  
   9: namespace NaT.SharePoint.EditControlBlockAudioSupport.WebControls
  10: {
  11:     
  12:     public class WindowsMediaPlayer : WebControl, INamingContainer
  13:     {
  14:         public string FileName{ get; set;}
  15:         protected override void Render(HtmlTextWriter writer)
  16:         {
  17:             base.Render(writer);
  18:             var template = this.GetResourceFileAsString("NaT.SharePoint.EditControlBlockAudioSupport.Properties.MediaPlayerObject.xml");
  19:             var outputMarkup = string.Format(template, "MediaPlayer_" + Guid.NewGuid().ToString(), FileName);
  20:             writer.Write(outputMarkup);
  21:         }
  22:         private static string GetResourceFileAsString(string fileName)
  23:         {
  24:             var assembly = Assembly.GetExecutingAssembly();
  25:             var stream = assembly.GetManifestResourceStream(fileName);
  26:             if (stream != null)
  27:             {
  28:                 var streamReader = new StreamReader(stream);
  29:                 var myText = streamReader.ReadToEnd();
  30:                 if (myText != null) return myText;
  31:             }
  32:             return string.Empty;
  33:         }
  34:     }
  35: }

Then, basically use the above WindowsMediaPlayer Web Control in your Media Player SharePoint application page.

 

Content Editor Web Part – JavaScript

   1: <script language="javascript">
   2: function IsAudioFile(m, ctx, itemId)
   3: { 
   4:    var request;
   5:    var url = ctx.HttpRoot + 
   6:     "/_layouts/NaT.SharePoint.EditControlBlockHandler/AudioCheckService.aspx?ListID=" + 
   7:     ctx.listName + "&ItemID=" + itemId+ "&AudioCheck=true";
   8:    
   9:    if ( window.XMLHttpRequest )
  10:    {
  11:       request = new XMLHttpRequest();
  12:       request.open("GET", url, false);
  13:       request.send(null);
  14:    }
  15:    else if ( window.ActiveXObject )
  16:    {
  17:       request = new ActiveXObject("Microsoft.XMLHTTP");
  18:       if ( request )
  19:       {
  20:          request.open("GET", url, false);
  21:          request.send(); 
  22:       }
  23:    }
  24:    if ( request )
  25:    {   
  26:       var commands = request.responseXML.getElementsByTagName("Command");
  27:       var cmdName = commands[0].firstChild.nodeValue;
  28:       if(cmdName == "true") return true;
  29:       else return false;
  30:    }
  31: }
  32:  
  33:  
  34: function Custom_AddDocLibMenuItems(m, ctx)
  35: {
  36:     if(IsAudioFile(m,ctx, currentItemID) == false) return false;
  37:     strAction="window.navigate(ctx.HttpRoot+;
  38:     '/_layouts/NaT.SharePoint.EditControlBlockHandler/AudioCheckService.aspx?ItemFileUrl='+
  39:     ctx.HttpRoot+currentItemFileUrl)"
  40:  
  41:     CAMOpt(m,"Play",strAction,"");
  42:     CAMSep(m);
  43:  
  44:     return false;
  45: }
  46:  
  47:  
  48: </script>

 

Your final out come should be something like this:

Play ECB

 

And, after clicking “Play”, you will be navigated to the media player application page.

 

Happy coding,

NaT

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (1)

Very very thanks for providing source code and nice reviews for audio players. This will help to all others to have best solution.

September 22, 2010 | Unregistered CommenterAshutosh Ranjan

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>