This page will display a scaled TV channel on screen and let you flip through channels. Play, pause, and channel change is handled using either SVG xlink:href or SMIL method calls. This example also uses TOI to listen to events from the mediaplayer. Both the .svg and the .js files are needed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg onload="onLoad()" onunload="onUnload()" id="root" version="1.2" width="100%" height="100%" top="0" left="0" position="fixed" viewBox="0 0 1280 720" preserveAspectRatio="none" viewport-fill="#C0C0C0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ekioh="http://www.ekioh.com/2007/ekioh" cursor="no" focusable="true" > <foreignObject id="toiJs2Plugin" requiredExtensions="application/x-motorola-toi" hidden="true"/> <g id="texts"> <text x="100" y="100">position=</text> <text x="100" y="120" id="player_pos">-</text> <text x="200" y="100">pace=</text> <text x="200" y="120" id="player_pace">-</text> <text x="300" y="100">keycode=</text> <text x="300" y="120" id="keycode">-</text> <text x="400" y="100">channel=</text> <text x="400" y="120" id="channel">-</text> <text x="500" y="100">Aspect=</text> <text x="500" y="120" id="aspect">-</text> <text x="230" y="150">URL=</text> <text x="330" y="150" id="videourl">URL</text> <text x="230" y="170">Resolution=</text> <text x="330" y="170" id="videoinfo">VIDEOINFO</text> </g> <video id='videoplane' x="224px" y="192px" width="608px" height="342px" preserveAspectRatio="xMidYMid" ekioh:colourKey="#ff000000" > </video> <g id="usage"> <text x="220" y="600" font-size="16" font-weight="bold" >Usage</text> <text x="250" y="620" fill="red">Red: Window size</text> <text x="370" y="620" fill="green">Green: Aspect r.</text> <text x="490" y="620" fill="yellow">Yellow: Fullscreen</text> <text x="620" y="620" fill="blue">Blue: Pause/Play</text> <text x="250" y="640">Up/Down: Change channel</text> </g> <script type="text/ecmascript" xlink:href="svg_smil_sample.js"></script> </svg>
var gSVGNS = "http://www.w3.org/2000/svg"; var gXLINKNS = "http://www.w3.org/1999/xlink"; var REGISTER_CALLBACKS = 1; var mediaPlayer = null; var video = null; var groupTexts = null; var groupUsage = null; var currentPace = 1000; var currAspectWidth = 16; var channels = [ "udp://224.5.5.1:11111", // bbc "udp://224.5.80.4:10000", "udp://224.5.80.6:10000", "udp://224.5.80.2:10000", "udp://224.5.5.1:11111", "udp://224.5.80.1:10000", // disc hd "udp://224.5.5.2:11111", "udp://224.5.80.5:10000" // tv6 ]; var nrChannels = channels.length; var currChan = 1; var flagFullscreen = 0; var flagAspectRatio = 0; var states = new Array("STATE_IDLE","STATE_CONNECTING","STATE_PLAYING","STATE_PAUSED","STATE_FAILED"); var reasons = new Array("REASON_COMMAND_COMPLETED","REASON_COMMAND_NOT_SUPPORTED","REASON_POSITION_EDGE", "REASON_ERROR_SERVER_UNAVAILABLE","REASON_ERROR_UNAUTHORIZED","REASON_ERROR_NOT_FOUND", "REASON_ERROR_NOT_ENOUGH_BANDWIDTH","REASON_ERROR_OTHER"); function onLoad() { /* * This line ensures that WebKit has completed page layout etc. before the rest of * the function is executed. If this is not done, the plugin will not be * available when called. */ document.addEventListener("keydown", onKeyDown, false); try { mediaPlayer = toi.mediaService.createPlayerInstance(); if (REGISTER_CALLBACKS != 0) { mediaPlayer.addEventListener(mediaPlayer.ON_STATE_CHANGED, onStateChanged); mediaPlayer.addEventListener(mediaPlayer.ON_POSITION_CHANGED, onPositionChanged); mediaPlayer.addEventListener(mediaPlayer.ON_STREAM_INFO_CHANGED, onStreamInfoChanged); } } catch(e) { alert("Failed creating player: " + e); } document.getElementById("keycode").textContent = "unset"; video = document.getElementById("videoplane"); groupTexts = document.getElementById("texts"); groupUsage = document.getElementById("usage"); startPlaying(); toggleAspectRatio(); } function onUnload() { try { if (mediaPlayer.getState() > 0) { mediaPlayer.close(); alert("Closed media player."); } if (REGISTER_CALLBACKS != 0) { mediaPlayer.removeEventListener(mediaPlayer.ON_STATE_CHANGED, onStateChanged); mediaPlayer.removeEventListener(mediaPlayer.ON_POSITION_CHANGED, onPositionChanged); mediaPlayer.removeEventListener(mediaPlayer.ON_STREAM_INFO_CHANGED, onStreamInfoChanged); } mediaPlayer.releaseInstance(); mediaPlayer = null; document.removeEventListener("keydown", onKeyDown, false); } catch(e) { alert("Onunload error:" + e); } } function startPlaying() { var url = channels[currChan]; video.endElement(); document.getElementById("channel").textContent = currChan; alert("startPlaying: " + url); document.getElementById("videourl").textContent = url; video.setAttributeNS(gXLINKNS, "href", url); video.beginElement(); currentPace = 1000; } function setPace(npace) { if (currentPace == 0 && npace == 1000) { video.resumeElement(); } else if (npace == 0) { video.pauseElement(); } else { alert("setPace: timed element does not support pace=" + npace); return; } currentPace = npace; document.getElementById("player_pace").textContent = currentPace; } function checkValidUpperChannel() { if (currChan >= nrChannels) { currChan = 0; } } function onKeyDown(ev) { var key = ev.keyIdentifier; alert("onKeyDown " + key); document.getElementById("keycode").textContent = key; if (key == "Up") { currChan = currChan + 1; startPlaying(); } else if (key == "Down") { currChan = currChan - 1; if (currChan <= 0) { currChan = nrChannels - 1; } startPlaying(); } else if (key == "Red") { toggleWindowsize(1); } else if (key == "Green") { toggleAspectRatio(); } else if (key == "Yellow") { flagFullscreen = 1 - flagFullscreen; setScreenWindow(); } else if (key == "Blue") { var newPace = 1000 - currentPace; setPace(newPace); } else if (key == "U+0031") { currChan = 1; checkValidUpperChannel(); startPlaying(); flagFullscreen = 1; setScreenWindow(); } else { alert("onKeyDown " + ev.keyIdentifier); } } function onStateChanged(ev) { try { alert("Media player state changed: state=" + states[ev.state] + ", reason=" + reasons[ev.reason] + ", code=" + ev.code); } catch(e) { alert("onPositionChanged problem: " + e); } } function onPositionChanged(ev) { try { var pos = ev.position; var pace = ev.pace; document.getElementById("player_pos").textContent = pos; document.getElementById("player_pace").textContent = pace; } catch(e) { alert("onPositionChanged problem: " + e); } } function onStreamInfoChanged() { if (mediaPlayer != null) { try { var si = mediaPlayer.getStreamInfo(); var videostreaminfo = null; var j = 0; var text = "(no info)"; for (j = 0; j < si.availableComponents.length; j++) { if (si.availableComponents[j].type == mediaPlayer.COMPONENT_VIDEO) { videostreaminfo = mediaPlayer.getVideoStreamInfo(si.availableComponents[j]); if (videostreaminfo != null) { text = videostreaminfo.resolutionX+" x "+videostreaminfo.resolutionY; } else { text = "Null object"; } } } document.getElementById("videoinfo").textContent = text; alert("onStreamInfoChanged " + text); } catch(e) { alert("onStreamInfoChanged problem: " + e); } } } function setScreenWindow() { if (flagFullscreen == 1) { video.setAttribute("x", 0); video.setAttribute("y", 0); video.setAttribute("width", 1280); video.setAttribute("height", 720); groupUsage.setAttribute("visibility", 'hidden'); } else { video.setAttribute("x", 224); video.setAttribute("y", 192); toggleWindowsize(0); groupUsage.setAttribute("visibility", 'visible'); } } function toggleAspectRatio() { flagAspectRatio = 1 - flagAspectRatio; var aspectText = null; if (flagAspectRatio == 0) { video.setAttribute("preserveAspectRatio","none"); aspectText = "strect"; } else { video.setAttribute("preserveAspectRatio","xMidYMid"); aspectText = "preserve aspect"; } document.getElementById("aspect").textContent = aspectText; } function toggleWindowsize(changeAspect) { if (flagFullscreen == 1) { return; } if (changeAspect != 0) { if (currAspectWidth == 12) { currAspectWidth = 16; } else { currAspectWidth = 12; } } if (currAspectWidth == 12) { video.setAttribute("width", 515); video.setAttribute("height", 384); } else { video.setAttribute("width", 608); video.setAttribute("height", 342); } }