Created
May 15, 2024 14:49
-
-
Save chrismcfee/04aa18d4b6c1f12ed920d5b40ed13040 to your computer and use it in GitHub Desktop.
zcast.worker.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const w = self; | |
| const RSS_DB = new Promise(function (resolve, reject) { | |
| var request = indexedDB.open('rssdata', 1); | |
| request.onerror = function (e) { | |
| reject("Database error: " + e.target.errorCode); | |
| }; | |
| request.onsuccess = function (e) { | |
| resolve(e.target.result); | |
| }; | |
| request.onupgradeneeded = function (e) { | |
| const store = e.target.result.createObjectStore('rssdata', { keyPath: 'id' }); | |
| store.createIndex('id','id', { 'unique': true }); | |
| } | |
| }); | |
| var RSS_UPDATE_TIMER; | |
| function playerLog(txt) { | |
| console.log(new Date() + ' - ' + txt); | |
| } | |
| function updateStore(id, data) { | |
| RSS_DB.then(function (db) { | |
| var store = db.transaction(['rssdata'], "readwrite").objectStore('rssdata'); | |
| var request = store.get(id); | |
| request.onerror = function (e) { | |
| console.log("Database error: " + e.target.errorCode); | |
| }; | |
| request.onsuccess = function (e) { | |
| var result = e.target.result; | |
| if (result) { | |
| result.data = data; | |
| result.lastUpdate = Date.now(); | |
| } else { | |
| result = { 'id': id, 'data': data, 'lastUpdate': Date.now() }; | |
| } | |
| store.put(result); | |
| }; | |
| }); | |
| } | |
| function getFromStore(id) { | |
| return RSS_DB.then(function (db) { | |
| var store = db.transaction(['rssdata'], "readwrite").objectStore('rssdata'); | |
| return new Promise(function (resolve, reject) { | |
| var request = store.index('id').get(id); | |
| request.onerror = function (e) { | |
| reject("Database error: " + e.target.errorCode); | |
| }; | |
| request.onsuccess = function (e) { | |
| var result = e.target.result; | |
| resolve(e.target.result || null); | |
| }; | |
| }); | |
| }); | |
| } | |
| function loadJSON(url) { | |
| if (typeof url !== 'string') return Promise.resolve(url); | |
| return new Promise(function (resolve, reject){ | |
| var xhr = new XMLHttpRequest(); | |
| xhr.responseType = 'json'; | |
| xhr.open('GET', url, true); | |
| xhr.onload = function (e) { | |
| var data = (typeof this.response === 'string')? JSON.parse(this.response) : this.response; | |
| resolve(data); | |
| }; | |
| xhr.onerror = function (e) { | |
| reject(e); | |
| } | |
| xhr.send(); | |
| }); | |
| } | |
| function updateRSS(serverUrl, media) { | |
| RSS_UPDATE_TIMER = setTimeout(updateRSS, 300000, serverUrl, media); | |
| loadRSS(serverUrl, media).then(function (feedInfo) { | |
| w.postMessage({ | |
| 'action': 'rssUpdate', | |
| 'feedInfo': feedInfo | |
| }); | |
| }); | |
| } | |
| function processScheduleData(serverUrl, data, IS_DEVICE) { | |
| return new Promise(function (resolve, reject) { | |
| const rssMedia = data.media? data.media.filter(function (media) { return media.mediaType === 'rss' }).map(function (media) { return media.id; }) : []; | |
| playerLog('Getting RSS...'); | |
| loadRSS(serverUrl, rssMedia).then(function (feedInfo) { | |
| playerLog('Formatting player data...'); | |
| const renderData = processRendererData(data, feedInfo, IS_DEVICE); | |
| RSS_UPDATE_TIMER && clearTimeout(RSS_UPDATE_TIMER); | |
| if (rssMedia.length > 0) { | |
| RSS_UPDATE_TIMER = setTimeout(updateRSS, 300000, serverUrl, rssMedia); | |
| } | |
| resolve(renderData); | |
| }, reject); | |
| }); | |
| } | |
| function processRendererData(data, feedInfo, IS_DEVICE) { | |
| playerLog('Processing data...'); | |
| const renderData = { | |
| 'campaign': {}, | |
| 'campaignItem': {}, | |
| 'layout': {}, | |
| 'zone': {}, | |
| 'mediaLoop': {}, | |
| 'mediaItem': {}, | |
| 'media': {} | |
| }; | |
| const output = { | |
| 'monitors': null | |
| }; | |
| var content; | |
| if('SITE_URL' in data){ | |
| output.SITE_URL = data.SITE_URL; | |
| } | |
| if('STATIC_URL' in data){ | |
| output.STATIC_URL = data.STATIC_URL; | |
| } | |
| if('MEDIA_URL' in data){ | |
| output.MEDIA_URL = data.MEDIA_URL; | |
| } | |
| if('version' in data){ | |
| output.version = data.version; | |
| } | |
| if ('devices' in data) { | |
| output.devices = data.devices; | |
| } | |
| if ('device' in data) { | |
| if (Array.isArray(data.device)) { | |
| output.device = { 'fields': data.device[0], 'model': 'cms.device', 'pk': data.device[0].id }; | |
| } else { | |
| output.device = data.device; | |
| } | |
| if (output.device.fields && 'assignedFields' in output.device.fields) { | |
| output.device.assignedFields = JSON.parse(output.device.fields['assignedFields']); | |
| } | |
| } | |
| data.media && data.media.forEach(function (media) { | |
| var mediaURL, mediaMeta; | |
| media.options = { 'volume': 1 }; | |
| if (isVideo(media)) { | |
| media.rendererType = 'video'; | |
| } else if (isAudio(media)) { | |
| media.rendererType = 'audio'; | |
| } else if (isImage(media)) { | |
| media.rendererType = 'image'; | |
| } else if (isStreaming(media)) { | |
| mediaMeta = (media.metaFields != '')? JSON.parse(media.metaFields) : {}; | |
| if (media.mediaType === 'rtmp') { | |
| if (mediaMeta.streamId) { | |
| mediaURL = media.external+'&streamId='+mediaMeta.streamId; | |
| } else { | |
| index = media.external.search(/(mp4|flv|mp3)\:.+/); | |
| mediaURL = media.external.substring(0, index)+'&streamId='+media.external.substring(index); | |
| } | |
| } else { | |
| mediaURL = media.external; | |
| } | |
| if (IS_DEVICE) { | |
| media.rendererType = 'stream'; | |
| media.external = mediaURL | |
| } else { | |
| media.rendererType = 'video'; | |
| media.location = mediaURL; | |
| media.streaming = true; | |
| } | |
| } else if (media.mediaType === 'text') { | |
| media.rendererType = 'text'; | |
| media.text = media.external? JSON.parse(media.external).svg : ''; | |
| media.style = { | |
| 'fontSize': (media.text.match(/(?<=font\-size\=)[0-9\"\']+/gi) || []).reduce(function (fontSizes, currentSize) { | |
| currentSize = parseInt(currentSize.trim().replace(/(^[\"\']{1}|[\"\']{1}$)/gi, ''), 10); | |
| if (fontSizes.indexOf(currentSize) === -1) { | |
| fontSizes.push(currentSize); | |
| } | |
| return fontSizes; | |
| }, []).sort(function (a, b) { | |
| return b - a; | |
| })[0] + 'px' | |
| }; | |
| } else { | |
| media.rendererType = media.mediaType; | |
| if (media.mediaType === 'rss') { | |
| media.feed = feedInfo[media.id]; | |
| } | |
| } | |
| if (media.external && media.external.charAt(0) === '{') { | |
| media.external = JSON.parse(media.external); | |
| } | |
| media.animation = media.animation? getTransitions(JSON.parse(media.animation)) : null; | |
| renderData.media[media.id] = media; | |
| }); | |
| data.mediaLoop && data.mediaLoop.forEach(function (mediaLoop) { | |
| mediaLoop.rendererType = 'loop'; | |
| mediaLoop.options = { 'volume': 1 }; | |
| mediaLoop.items = []; | |
| mediaLoop.widgetItems = {}; | |
| renderData.mediaLoop[mediaLoop.id] = mediaLoop; | |
| }); | |
| data.mediaItem && data.mediaItem.forEach(function (mediaItem) { | |
| const mediaItemId = mediaItem.id; | |
| const loopId = mediaItem.loop || mediaItem.loopId; | |
| const loop = loopId? renderData.mediaLoop[loopId] : null; | |
| const mediaId = mediaItem.media || mediaItem.mediaId; | |
| mediaItem.options = { 'volume': 1 }; | |
| mediaItem.style = mediaItem.style? JSON.parse(mediaItem.style) : {}; | |
| mediaItem.animation = mediaItem.animation? getTransitions(JSON.parse(mediaItem.animation)) : null; | |
| if (mediaItem.widget) { | |
| mediaItem.rendererType = 'widget'; | |
| mediaItem.text = JSON.parse(mediaItem.text); | |
| if (mediaItem.widgetType === 'FileGallery') { | |
| let zone = data.zone.filter((z)=>z.content_type==='cms.mediaitem'&&z.object_id===mediaItemId)[0]; | |
| if (data.schedule && data.schedule.length > 0) { | |
| let tempId = 'filegallery-'+mediaItemId; | |
| zone.content_type = 'cms.medialoop'; | |
| zone.object_id = tempId; | |
| renderData.mediaLoop[tempId] = { | |
| 'id': tempId, | |
| 'name': tempId, | |
| 'created': mediaItem.created, | |
| 'groupings': [], | |
| 'modified': mediaItem.modified, | |
| 'hardwareProfile': null, | |
| 'rendererType': 'loop', | |
| 'options': { 'volume': 1 }, | |
| 'items': [], | |
| 'widgetItems': {}, | |
| 'tags': [] | |
| }; | |
| data.media.filter((m)=>{ | |
| return m.rendererType !== "swf" && m.groupings.indexOf(parseInt(mediaItem.text.options.grouping,10)) !== -1; | |
| }).forEach((m,index)=>{ | |
| let id = tempId+'-media-'+m.id; | |
| renderData.mediaItem[id] = Object.assign({}, renderData.media[m.id], { | |
| "options": { 'volume': 1 }, | |
| "style": {}, | |
| "widgetType": null, | |
| "tags": [], | |
| "media": m.id, | |
| "widget": false, | |
| "streamType": null, | |
| "animation": mediaItem.text.options.animation, | |
| "text": '', | |
| "duration": Math.min(Math.max(mediaItem.text.options.minDuration, m.duration),mediaItem.text.options.maxDuration), | |
| "position": index+1, | |
| "id": id, | |
| "loop": tempId, | |
| "name": m.name, | |
| "mediaModified": m.modified | |
| }); | |
| renderData.mediaLoop[tempId].items.push(renderData.mediaItem[id]); | |
| }); | |
| return; | |
| } else if (zone.display_constraint) { | |
| mediaItem.text.options.display_constraint = JSON.parse(zone.display_constraint); | |
| } | |
| } | |
| } else if (mediaId) { | |
| let media = renderData.media[mediaId]; | |
| mediaItem = Object.assign({}, media, mediaItem); | |
| mediaItem.name = media.name; | |
| mediaItem.mediaModified = media.modified; | |
| if (mediaItem.streaming || mediaItem.rendererType === "stream" && IS_DEVICE) { | |
| mediaItem.rendererType = 'external'; | |
| } | |
| if (mediaItem.text.charAt(0) === '{') { | |
| mediaItem.text = JSON.parse(mediaItem.text); | |
| mediaItem.text = JSON.parse(mediaItem.text); | |
| if (mediaItem.text.playExternal && IS_DEVICE) { | |
| mediaItem.rendererType = 'external'; | |
| } | |
| } | |
| if (media.mediaType === 'text') { | |
| mediaItem.text = media.text; | |
| Object.assign(mediaItem.style, media.textStyle); | |
| } | |
| } else if (mediaItem.streamType) { | |
| mediaItem.rendererType = 'local'; | |
| mediaItem.text = JSON.parse(mediaItem.text); | |
| } else { | |
| mediaItem.rendererType = 'text'; | |
| mediaItem.originalText = mediaItem.text; | |
| mediaItem.text = mediaItemToHTMLText(mediaItem); | |
| } | |
| renderData.mediaItem[mediaItem.id] = mediaItem; | |
| if (loop) { | |
| loop.items.push(mediaItem); | |
| loop.items.sort(function (a,b) { return a.position - b.position; }); | |
| if (mediaItem.widget) { | |
| loop.widgetItems[mediaItem.id] = mediaItem; | |
| } | |
| } | |
| }); | |
| data.layout && data.layout.forEach(function (layout) { | |
| const w = layout.resolutionHeight; | |
| const h = layout.resolutionWidth; | |
| var delta; | |
| layout.options = { 'volume': layout.muteVideo? 0 : 1 }; | |
| layout.zones = []; | |
| layout.widgetItems = {}; | |
| if (layout.object_id && layout.content_type) { | |
| layout.audio = renderData.media[layout.object_id]; | |
| } | |
| layout.rendererType = 'layout'; | |
| layout.style = layout.style? JSON.parse(layout.style) : {}; | |
| if (layout.style.transform) { | |
| delta = (layout.resolutionWidth - layout.resolutionHeight) / 2; | |
| layout.style.left = delta + 'px'; | |
| layout.style.top = (delta*-1) + 'px'; | |
| } | |
| layout.animation = layout.animation? getTransitions(JSON.parse(layout.animation)) : null; | |
| renderData.layout[layout.id] = layout; | |
| }); | |
| data.zone && data.zone.forEach(function (zone) { | |
| const contentType = (zone.content_type === 'cms.medialoop')? 'mediaLoop' : (zone.content_type === 'cms.mediaitem')? 'mediaItem' : 'layout'; | |
| const layout = renderData.layout[zone.layout || zone.layoutId]; | |
| zone.rendererType = 'zone'; | |
| zone.content = renderData[contentType][zone.object_id]; | |
| zone.style = zone.style? JSON.parse(zone.style) : {}; | |
| zone.animation = zone.animation? getTransitions(JSON.parse(zone.animation)) : null; | |
| zone.multitouch = zone.multitouch? JSON.parse(zone.multitouch) : null; | |
| zone.options = Object.assign({ 'volume': 1 }, zone.text? JSON.parse(zone.text) : {}); | |
| zone.display_constraint = zone.display_constraint? JSON.parse(zone.display_constraint) : null; | |
| renderData.zone[zone.id] = zone; | |
| layout.zones.push(zone); | |
| if (zone.content) { | |
| if (zone.content.widgetItems) { | |
| layout.widgetItems = Object.assign(layout.widgetItems, zone.content.widgetItems); | |
| } else if (zone.content.widget) { | |
| layout.widgetItems[zone.content.id] = zone.content; | |
| } | |
| } | |
| }); | |
| data.campaign && data.campaign.forEach(function (campaign) { | |
| campaign.rendererType = 'campaign'; | |
| campaign.items = []; | |
| campaign.widgetItems = {}; | |
| renderData.campaign[campaign.id] = campaign; | |
| }); | |
| data.campaignItem && data.campaignItem.forEach(function (campaignItem) { | |
| const campaign = renderData.campaign[campaignItem.campaign || campaignItem.campaignId]; | |
| var contentType; | |
| if (campaignItem.content_type === 'cms.layout') { | |
| contentType = 'layout'; | |
| } else if (campaignItem.content_type === 'cms.medialoop') { | |
| contentType = 'mediaLoop'; | |
| } else { | |
| contentType = 'media'; | |
| } | |
| campaignItem.content = renderData[contentType][campaignItem.object_id]; | |
| campaignItem.animation = campaignItem.animation? getTransitions(JSON.parse(campaignItem.animation)) : null; | |
| if (campaignItem.content) { | |
| campaignItem.content = JSON.parse(JSON.stringify(campaignItem.content)); | |
| campaignItem.content.duration = campaignItem.duration; | |
| if (campaignItem.animation) { | |
| campaignItem.content.animation = campaignItem.animation; | |
| } | |
| } | |
| renderData.campaignItem[campaignItem.id] = campaignItem; | |
| campaign.items.push(campaignItem); | |
| campaign.items.sort(function (a, b) { return a.position - b.position; }); | |
| if (campaignItem.content && campaignItem.content.widgetItems) { | |
| campaign.widgetItems = Object.assign(campaign.widgetItems, campaignItem.content.widgetItems); | |
| } | |
| }); | |
| data.schedule && data.schedule.forEach(function (schedule) { | |
| if (schedule.content_type === 'cms.campaign') { | |
| schedule.content_type = 'campaign'; | |
| } else if (schedule.content_type === 'cms.layout') { | |
| schedule.content_type = 'layout'; | |
| } else if (schedule.content_type === 'cms.medialoop') { | |
| schedule.content_type = 'mediaLoop'; | |
| } else { | |
| schedule.content_type = 'media'; | |
| } | |
| schedule.content = renderData[schedule.content_type][schedule.object_id]; | |
| }); | |
| if (!data.schedule) { | |
| if (data.campaign) { | |
| content = renderData.campaign[data.campaign[0].id]; | |
| } else if (data.layout) { | |
| content = renderData.layout[data.layout[0].id]; | |
| } else if (data.mediaLoop) { | |
| content = renderData.mediaLoop[data.mediaLoop[0].id]; | |
| } else if (data.media) { | |
| content = renderData.media[data.media[0].id]; | |
| } | |
| if (!data.monitor || data.monitor.length === 0) { | |
| output.monitors = [ Object.assign(getDefaultMonitor(), { 'content': content }) ]; | |
| } else { | |
| output.monitors = data.monitor.filter(filterMatchingIds).map(function (monitor) { | |
| return Object.assign(monitor, { 'content': content }); | |
| }); | |
| } | |
| } else { | |
| output.monitors = filterMonitorsById(data.monitor).map(function (monitor) { | |
| const content = { | |
| 'schedule': data.schedule.filter(function (schedule) { | |
| return schedule.monitors.indexOf(monitor.id) > -1; | |
| }) | |
| }; | |
| if (monitor.displayRotation) { | |
| if (monitor.displayRotation % 180 > 0) { | |
| let w = monitor.displayWidth || monitor.resolutionWidth; | |
| let h = monitor.displayHeight || monitor.resolutionHeight; | |
| let diff = w - h; | |
| monitor.displayTop = monitor.displayTop + (diff / 2); | |
| monitor.displayLeft = monitor.displayLeft - (diff / 2); | |
| monitor.transform = 'rotate(' + monitor.displayRotation + 'deg)'; | |
| } else { | |
| monitor.transform = 'rotate(' + monitor.displayRotation + 'deg)'; | |
| } | |
| } | |
| if (monitor.assignedFields) { | |
| monitor.assignedFields = JSON.parse(monitor.assignedFields); | |
| } else { | |
| monitor.assignedFields = {}; | |
| } | |
| return Object.assign(monitor, { 'content': content }); | |
| }); | |
| } | |
| return output; | |
| } | |
| function filterMonitorsById(monitors) { | |
| var ids = []; | |
| var output = []; | |
| for (var i = 0; i < monitors.length; i++) { | |
| if (ids.indexOf(monitors[i].id) === -1 && monitors[i].scheduled) { | |
| ids.push(monitors[i].id); | |
| output.push(monitors[i]); | |
| } | |
| } | |
| return output.sort(function (a, b) { | |
| return a.id - b.id; | |
| }); | |
| } | |
| function filterMatchingIds(current, index, arr) { | |
| for (var i = 0; i < index; i++) { | |
| if (arr[index].id === current.id) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| function isVideo(media) { | |
| return (['mp4','ogg','ogv','webm','mov','flv','mkv','3gp','wmv','qt','divx','mpeg','avi','m2v','mp2','3g2','ts','mxf','rmvb', 'm4v'].indexOf(media.mediaType) !== -1); | |
| } | |
| function isAudio(media) { | |
| return (['mp3','aac','wav','m4a','wma','aif','aifc','flac','ape','opus'].indexOf(media.mediaType) !== -1); | |
| } | |
| function isImage(media) { | |
| return (['jpg','jpeg','gif','png','svg','bmp','webp','tiff','psd','ai','svgz','j2k','jp2','pcx','wmf','eps','epsi','tga','dib','xbm','xcf','xwd','bpg','iff'].indexOf(media.mediaType) !== -1); | |
| } | |
| function isStreaming(media) { | |
| return (['rtmp','rtsp','udp','rtpts','rtpavp'].indexOf(media.mediaType) !== -1); | |
| } | |
| function isText(media) { | |
| return (['text'].indexOf(media.mediaType) !== -1); | |
| } | |
| function sortKeyframes(a, b) { | |
| return a.position - b.position; | |
| } | |
| function getTransitions(animation) { | |
| var output = {}; | |
| var hasTransition = false; | |
| if ('timeline' in animation) { | |
| output.timeline = animation.timeline; | |
| output.timeline.translate.sort(sortKeyframes); | |
| output.timeline.rotate.sort(sortKeyframes); | |
| output.timeline.scale.sort(sortKeyframes); | |
| output.timeline.skew.sort(sortKeyframes); | |
| output.timeline.opacity.sort(sortKeyframes); | |
| output.timeline.clip.sort(sortKeyframes); | |
| hasTransition = true; | |
| } | |
| if ('transitionIn' in animation && animation.transitionIn.duration) { | |
| output['in'] = { | |
| 'overlap': animation.transitionIn.overlap || false, | |
| 'duration': animation.transitionIn.duration * 1000, | |
| 'direction': animation.transitionIn.direction, | |
| 'fade': (animation.transitionIn.blend === 'fade')? true : false, | |
| 'slide': (animation.transitionIn.direction !== 'none' && (animation.transitionIn.blend !== 'clip' && animation.transitionIn.blend !== 'flip' && animation.transitionIn.blend !== 'centerflip' && animation.transitionIn.blend !== 'fade'))? true : false, | |
| 'clip': (animation.transitionIn.blend === 'clip')? true : false, | |
| 'flip': (animation.transitionIn.blend === 'flip')? true : false, | |
| 'centerflip': (animation.transitionIn.blend === 'centerflip')? true : false, | |
| 'rotations': ('rotations' in animation.transitionIn)? parseInt(animation.transitionIn.rotations,10) : 0, | |
| 'zoom': (animation.transitionIn.blend && animation.transitionIn.blend.indexOf('zoom') !== -1)? true : false, | |
| 'easing': animation.transitionIn.easing || 'linear' | |
| }; | |
| output.in.zoomtype = (output.in.zoom)? animation.transitionIn.blend : null; | |
| hasTransition = true; | |
| } | |
| if ('transitionOut' in animation && animation.transitionOut.duration) { | |
| output['out'] = { | |
| 'overlap': animation.transitionOut.overlap || false, | |
| 'duration': animation.transitionOut.duration * 1000, | |
| 'direction': animation.transitionOut.direction, | |
| 'fade': (animation.transitionOut.blend === 'fade')? true : false, | |
| 'slide': (animation.transitionOut.direction !== 'none' && (animation.transitionOut.blend !== 'clip' && animation.transitionOut.blend !== 'flip' && animation.transitionOut.blend !== 'centerflip' && animation.transitionIn.blend !== 'fade'))? true : false, | |
| 'clip': (animation.transitionOut.blend === 'clip')? true : false, | |
| 'flip': (animation.transitionOut.blend === 'flip')? true : false, | |
| 'centerflip': (animation.transitionOut.blend === 'centerflip')? true : false, | |
| 'rotations': ('rotations' in animation.transitionOut)? parseInt(animation.transitionOut.rotations,10) : 0, | |
| 'zoom': (animation.transitionOut.blend && animation.transitionOut.blend.indexOf('zoom') !== -1)? true : false, | |
| 'easing': animation.transitionOut.easing || 'linear' | |
| }; | |
| output.out.zoomtype = (output.out.zoom)? animation.transitionOut.blend : null; | |
| hasTransition = true; | |
| } | |
| if ('scroll' in animation && animation.scroll.duration) { | |
| output['scroll'] = { | |
| 'direction': animation.scroll.direction, | |
| 'duration': animation.scroll.duration * 1000, | |
| 'pause': animation.scroll.pause * 1000, | |
| 'easing': animation.scroll.easing || 'linear', | |
| 'seamless': animation.scroll.seamless || false | |
| }; | |
| hasTransition = true; | |
| } | |
| if ('cover' in animation) { | |
| output['cover'] = JSON.parse(JSON.stringify(animation)).cover; | |
| if (output.cover.in && output.cover.in.duration) { | |
| output.cover.in.duration *= 1000; | |
| output.cover.in.delay *= 1000; | |
| } | |
| if (output.cover.out && output.cover.out.duration) { | |
| output.cover.out.duration *= 1000; | |
| output.cover.out.delay *= 1000; | |
| } | |
| hasTransition = true; | |
| } | |
| return hasTransition? output : null; | |
| } | |
| function mediaItemToHTMLText(mediaItem){ | |
| let mediaItemStyle = mediaItem.style || {}; | |
| if (typeof mediaItemStyle === 'string') { | |
| mediaItemStyle = JSON.parse(mediaItemStyle); | |
| } | |
| return ('styles' in mediaItemStyle)? createTextFromFabricJS(mediaItem.text,mediaItemStyle) : mediaItem.text; | |
| } | |
| function createTextFromFabricJS(original_text,mediaItemStyle){ | |
| var text = ''; | |
| var lines = original_text.split(/\n|\r/gi); | |
| var total = lines.length; | |
| var end = total - 1; | |
| var line, newLine, currentChar, currentStyles, val, filterText, strokeW; | |
| for(var l = 0; l < total; l++){ | |
| if(l.toString() in mediaItemStyle.styles){ | |
| line = lines[l]; | |
| newLine = ''; | |
| for(var c = 0; c < line.length; c++){ | |
| currentChar = line.charAt(c); | |
| if(c.toString() in mediaItemStyle.styles[l]){ | |
| currentStyles = ''; | |
| for(var s in mediaItemStyle.styles[l][c]){ | |
| val = mediaItemStyle.styles[l][c][s]; | |
| switch(s){ | |
| case 'fill': | |
| if(!('color' in mediaItemStyle) || mediaItemStyle.color != val){ | |
| currentStyles += ('color:'+val+';'); | |
| } | |
| break; | |
| case 'fontWeight': | |
| if(!('fontWeight' in mediaItemStyle) || mediaItemStyle.fontWeight != val){ | |
| currentStyles += ('font-weight:'+val+';'); | |
| } | |
| break; | |
| case 'fontStyle': | |
| if(!('fontStyle' in mediaItemStyle) || mediaItemStyle.fontStyle != val){ | |
| currentStyles += ('font-style:'+val+';'); | |
| } | |
| break; | |
| case 'fontFamily': | |
| if(!('fontFamily' in mediaItemStyle) || mediaItemStyle.fontFamily != val){ | |
| currentStyles += ('font-family:'+val+';'); | |
| } | |
| break; | |
| case 'fontSize': | |
| if(!('fontSize' in mediaItemStyle) || mediaItemStyle.fontSize != val+'px'){ | |
| currentStyles += ('font-size:'+val+'px;'); | |
| } | |
| break; | |
| case 'textDecoration': | |
| if(!('textDecoration' in mediaItemStyle) || mediaItemStyle.textDecoration != val){ | |
| currentStyles += ('text-decoration:'+val+';'); | |
| } | |
| break; | |
| case 'stroke': | |
| strokeW = mediaItemStyle.styles[l][c]['strokeWidth']+'px'; | |
| val = strokeW + ' ' + val; | |
| if(!('textStroke' in mediaItemStyle) || mediaItemStyle.textStroke != val){ | |
| currentStyles += ('-webkit-text-stroke:'+val+';'); | |
| currentStyles += ('text-stroke:'+val+';'); | |
| } | |
| break; | |
| case 'shadow': | |
| val = val.color + ' ' + val.offsetX + ' ' + val.offsetY + ' ' + val.blur; | |
| if(!('textStroke' in mediaItemStyle) || mediaItemStyle.textStroke != val){ | |
| currentStyles += ('text-shadow:'+val); | |
| } | |
| break; | |
| } | |
| } | |
| if (currentStyles){ | |
| newLine += '<span style="'+currentStyles+'">'+currentChar+'</span>'; | |
| } else { | |
| newLine += currentChar; | |
| } | |
| } else { | |
| newLine += currentChar; | |
| } | |
| } | |
| text += newLine; | |
| } else { | |
| text += lines[l]; | |
| } | |
| if (l < end) { | |
| text += '<br>'; | |
| } | |
| } | |
| return text; | |
| } | |
| function loadRSS(serverUrl, mediaIds) { | |
| if (!mediaIds || mediaIds.length === 0) return Promise.resolve({}); | |
| const serverPath = pathJoin(serverUrl? serverUrl : ServerInfo.getPath(), "zcast/proxy/?id="); | |
| const output = {}; | |
| return Promise.all(mediaIds.map(function (mediaId) { | |
| if (!navigator.onLine) return loadLoacalRSS(mediaId, output); | |
| return loadJSON(serverPath + mediaId).then(function (data) { | |
| output[mediaId] = data; | |
| updateStore(mediaId, JSON.stringify(data)); | |
| return Promise.resolve(); | |
| }, function (err) { | |
| console.error('Unable to get feed with id ' + mediaId); | |
| return loadLoacalRSS(mediaId, output); | |
| }); | |
| })).then(function () { | |
| return Promise.resolve(output); | |
| }); | |
| } | |
| function loadLoacalRSS(id, output) { | |
| return getFromStore(id).then(function (data) { | |
| if (data) { | |
| output[data.id] = JSON.parse(data.data); | |
| } | |
| return Promise.resolve(); | |
| }); | |
| } | |
| function pathJoin() { | |
| var parts = []; | |
| var part; | |
| if (arguments.length === 0) { | |
| return ''; | |
| } else if (arguments.length === 1) { | |
| return arguments[0]; | |
| } | |
| for (var i = 0; i < arguments.length; i++) { | |
| part = arguments[i]; | |
| // Get rid of leading slash if not leading double slash | |
| if (part.charAt(0) === '/' && part.substring(0,2) !== '//') { | |
| part = part.substring(1); | |
| } | |
| // Get rid of trailing slash | |
| if (part.charAt(part.length - 1) === '/') { | |
| part = part.substring(0, part.length - 1); | |
| } | |
| parts.push(part); | |
| } | |
| return parts.join('/'); | |
| } | |
| function getDefaultMonitor() { | |
| return { | |
| 'id': 'default', | |
| 'name': 'Preview', | |
| 'displayLeft': 0, | |
| 'displayTop': 0, | |
| 'displayRotation': 0, | |
| 'width': 0, | |
| 'height': 0, | |
| 'rotation': 0 | |
| }; | |
| } | |
| function getErrorMsg(err) { | |
| if (typeof err === 'string') return err; | |
| return err.message || err.toString(); | |
| } | |
| w.onmessage = function (e) { | |
| const WORKER_PROMISE_ID = ('WORKER_PROMISE_ID' in e.data)? e.data.WORKER_PROMISE_ID : null; | |
| if (e.data.action === 'loadSchedule') { | |
| playerLog('Getting schedule data...'); | |
| loadJSON(e.data.url).then(function (data) { | |
| // TODO: This is where data comparison should take place to see if updates need to happen to already running content | |
| const serverUrl = data.SITE_URL || e.data.server; | |
| return processScheduleData(serverUrl, data, e.data.IS_DEVICE); | |
| }).then(function (scheduleInfo) { | |
| w.postMessage({ | |
| 'WORKER_PROMISE_ID': WORKER_PROMISE_ID, | |
| 'action': 'scheduleUpdate', | |
| 'data': scheduleInfo | |
| }); | |
| }, function (err) { | |
| w.postMessage({ | |
| 'WORKER_PROMISE_ID': WORKER_PROMISE_ID, | |
| 'action': 'scheduleUpdate', | |
| 'error': getErrorMsg(err) | |
| }); | |
| }); | |
| } else if (e.data.action === 'rssStop') { | |
| RSS_UPDATE_TIMER && clearTimeout(RSS_UPDATE_TIMER); | |
| console.log('RSS Updates halted.'); | |
| } else if (e.data.action === 'testCAP') { | |
| testCAP().then(function (data) { | |
| w.postMessage({ | |
| 'WORKER_PROMISE_ID': WORKER_PROMISE_ID, | |
| 'action': 'CAP', | |
| 'data': data | |
| }); | |
| }, function (err) { | |
| w.postMessage({ | |
| 'WORKER_PROMISE_ID': WORKER_PROMISE_ID, | |
| 'action': 'CAP', | |
| 'error': getErrorMsg(err) | |
| }); | |
| }); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment