Author: ygrego Date: 2015-05-13 15:36:40 +0000 (Wed, 13 May 2015) New Revision: 1340 Url: http://forge.nuiton.org/projects/sandbox/repository/revisions/1340 Log: General refactoring of implementation. Added: oipf/js/configuration/ConfigDefaultProperties.js oipf/js/impl/model/Recording.js oipf/js/impl/model/ScheduledRecording.js oipf/js/impl/model/ScheduledRecordingCollection.js oipf/js/impl/model/constants/ConfigurationConstants.js oipf/js/impl/model/constants/RecordingSchedulerConstants.js oipf/js/test/CapabilitiesTest.js oipf/js/test/ConfigurationTest.js oipf/js/test/newjavascript.js oipf/js/utils/DateUtils.js oipf/js/utils/MetaData.js oipf/js/utils/OrderingUtils.js oipf/js/utils/TimerRecordingManager.js Modified: oipf/js/configuration/CapabilitiesProperties.js oipf/js/configuration/TestConfig.js oipf/js/impl/CapabilitiesObject.js oipf/js/impl/ConfigurationObject.js oipf/js/impl/RecordingSchedulerObject.js oipf/js/impl/model/Channel.js oipf/js/impl/model/Configuration.js oipf/js/impl/model/IntegerCollection.js oipf/js/impl/model/LocalSystem.js oipf/js/impl/model/MetadataSearch.js oipf/js/impl/model/ModelFactory.js oipf/js/impl/model/Programme.js oipf/js/impl/model/SearchResults.js oipf/js/impl/model/SignalInfo.js oipf/js/impl/model/Tuner.js oipf/js/impl/model/constants/DaeMimeType.js oipf/js/impl/model/constants/VideoBroadcastConstants.js oipf/js/initObj/init.js oipf/js/test/RecordingSchedulerTest.js oipf/js/test/SearchManagerTest.js oipf/js/test/Test.js oipf/js/test/TestCase.js oipf/js/test/VideoBroadcastTest.js oipf/js/utils/EventManager.js oipf/js/utils/Utils.js oipf/js/utils/XmlParser.js Modified: oipf/js/configuration/CapabilitiesProperties.js =================================================================== --- oipf/js/configuration/CapabilitiesProperties.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/configuration/CapabilitiesProperties.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -3,146 +3,155 @@ * the mime type application/oipfCapabilities. */ var CapabilitiesProperties = Class.extend({ + defaultConfig: { + extraSDVideoDecodes: null, + extraHDVideoDecodes: null + }, + + baseUIProfileName: [ + "OITF_SDEU_UIPROF", + "OITF_SD60_UIPROF", + "OITF_SDUS_UIPROF", + "OITF_HD_UIPROF", + "OITF_FULL_HD_UIPROF" + ], + + UIProfileNameFragment: [ + "+TRICKMODE", + "+AVCAD", + "+DL", + "+IPTV_SDS", + "+IPTV_URI", + "+ANA", + "+DVB_C", + "+DVB_T", + "+DVB_S", + "+DVB_C2", + "+DVB_T2", + "+DVB_S2", + "+META_BCG", + "+META_EIT", + "+META_SI", + "+ITV_KEYS", + "+CONTROLLED", + "+PVR", + "+DRM", + "+CommunicationServices", + "+SVG", + "+POINTER", + "+WIDGETS", + "+HTML5_MEDIA", + "+RCF", + "+TELEPHONY", + "+VIDEOTELEPHONY" + ], + profileNameMapping: { - "+TRICKMODE": { - value: [ - "VK_PLAY", - "VK_PAUSE", - "VK_PLAY_PAUSE", - "VK_STOP", - "VK_REWIND", - "VK_FAST_FWD"] - }, - "+ITV_KEYS": { - value: [ - "VK_HOME", - "VK_MENU", - "VK_CANCEL", - "VK_SUBTITLE"] - }, - "+CONTROLLED": { - value: [ - "VK_CHANNEL_UP", - "VK_CHANNEL_DOWN", - "VK_VOLUME_UP", - "VK_VOLUME_DOWN", - "VK_MUTE"], - tagName: [ - "configurationChanges", - "extendedAVControl", - "remote_diagnostics" - ] - }, - "+PVR": { - value: "VK_RECORD", - tagName: "recording", - }, - "+DRM": { - tagName: "drm", - }, - "+CommunicationServices": { - tagName: "communicationServices", - }, - "+SVG": { - tagName: "mime-extensions", - }, - "+POINTER": { - tagName: "pointer", - }, - "+WIDGETS": { - tagName: "widgets", - }, - "+HTML5_MEDIA": { - tagName: "html5_media", - }, - "+RCF": { - tagName: "remoteControlFunction", - }, - "+AVCAD": { - attributeValue: "application/vnd.oipf.ContentAccessStreaming+xml" - }, - "+DL": { - attributeValue: "http" - }, - "+IPTV_SDS": { - attributeValue: "ID_IPTV_SDS" - }, - "+IPTV_URI": { - attributeValue: "ID_IPTV_URI" - }, - "+ANA": { - attributeValue: "ID_ANALOG" - }, - "+DVB_C": { - attributeValue: "ID_DVB_C ID_DVB_SI_DIRECT" - }, - "+DVB_T": { - attributeValue: "ID_DVB_T ID_DVB_SI_DIRECT" - }, - "+DVB_S": { - attributeValue: "ID_DVB_S ID_DVB_SI_DIRECT" - }, - "+DVB_C2": { - attributeValue: "ID_DVB_C2 ID_DVB_SI_DIRECT" - }, - "+DVB_T2": { - attributeValue: "ID_DVB_T2 ID_DVB_SI_DIRECT" - }, - "+DVB_S2": { - attributeValue: "ID_DVB_S2 ID_DVB_SI_DIRECT" - }, - "+META_BCG": { - attributeValue: "bcg" - }, - "+META_EIT": { - attributeValue: "eit-pf" - }, - "+META_SI": { - attributeValue: "dvb-si" - } + "+DVB_T": "DVB", + "+META_EIT": "META" + /*"+AVCAD": "DVB", + "+IPTV_SDS": "DVB", + "+IPTV_URI": "DVB", + "+ANA": "DVB", + "+DVB_C": "DVB", + "+DVB_S": "DVB", + "+DVB_C2": "DVB", + "+DVB_T2": "DVB", + "+DVB_S2": "DVB", + "+META_BCG": "META", + "+META_SI": "META"*/ }, roots: "profilelist", - default: { - "video_broadcast": { - "value": true, - "attributes": { - type: "ID_DVB_S ID_DVB_T", - transport: "", - nrstreams: 1, - scaling: "arbitrary", - minSize: 0, - postList: false, - networkTimeshift: false, - localTimeshift: false + defaultCapabilities: { + "DVB": { + video_broadcast: { + value: true, + attributes: { + type: "ID_DVB_T ID_DVB_SI_DIRECT", + transport: "", + nrstreams: 1, + scaling: "arbitrary", + minSize: 0, + postList: false, + networkTimeshift: false, + localTimeshift: false + } } }, - "overlaylocaltuner": { - "value": "per-pixel", + "OITF_SDEU_UIPROF": { + overlaylocaltuner: { + value: "per-pixel" + } }, - "recording": { - "value": true, - "attributes": { - ipBroadcast: false, - HAS: false, - DASH: false, - manageRecordings: "initiator", - postList: false + "+PVR": { + recording: { + value: true, + attributes: { + ipBroadcast: false, + HAS: false, + DASH: false, + manageRecordings: "initiator", + postList: false + } } }, - "clientMetadata": { - "value": true, - "attributes": { - type: "eit-pf" + META: { + clientMetadata: { + value: true, + attributes: { + type: "eit-pf" + } } }, - "configurationChanges": { - "value": true, - "attributes": { - + "+CONTROLLED": { + configurationChanges: { + value: true } } + }, + + rearrangeDefaultProperties: function() { + var defaultProperties = {}; + + var defaultCapabilitiesKeys = Object.keys(this.defaultCapabilities); + + for (var i = 0, l = defaultCapabilitiesKeys.length; i < l; i++) { + var currentKey = defaultCapabilitiesKeys[i]; + var currentCapability = this.defaultCapabilities[currentKey]; + var currentCapabilityKeysList = Object.keys(currentCapability); + + for (var j = 0, l1 = currentCapabilityKeysList.length; j < l1; j++) { + var currentCapabilityKeys = currentCapabilityKeysList[j]; + defaultProperties[currentCapabilityKeys] = + currentCapability[currentCapabilityKeys]; + } + } + return defaultProperties; + }, + + /* + * FIXME: + * Yannis - 13/05/2015 - Achieved a more detailed verification on capability + * but it's not an obligation + */ + hasCapablity: function(profileName) { + this.defaultCapabilities[profileName]; + this.profileNameMapping[profileName]; + + return this.defaultCapabilities[profileName] || + this.profileNameMapping[profileName]; + }, + + searchAnAttributeValue: function(attributeValue) { + + }, + searchATagName: function(tagName) { + + }, + searchAValue: function(value) { + } }); Added: oipf/js/configuration/ConfigDefaultProperties.js =================================================================== --- oipf/js/configuration/ConfigDefaultProperties.js (rev 0) +++ oipf/js/configuration/ConfigDefaultProperties.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,135 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var ConfigDefaultProperties = Class.extend({ + + init: function() { + + this.restrictedPowerState = { + 0: true, // OFF + 6: true // FACTORY_RESET + }, + + this.tvStandardsSupported = { + 1: true, + 2: true, + 4: true, + 8: true, + 16: true + }, + + this.screenSize = { + "1280x720": true, //HD 720 + "1920x1080": true, //HD 1080 + "640x480": true //VGA + }, + + this.configuration = { + preferredAudioLanguage: "fra", + preferredSubtitleLanguage: "fra", + preferredUILanguage: "fra", + countryId: "FRA", + regionId: 0, + pvrPolicy: configurationConstants.pvrPolicy.WATCHED_RECORDINGS, + pvrSaveEpisodes: 5, + pvrSaveDays: 15, + pvrStartPadding: 0, //Measured in (s) + pvrEndPadding: 0, //Measured in (s) + preferredTimeShiftMode: videoBroadcastConstants.timeShiftMode.OFF + }; + + this.startupInformation = { + urlSource: null, + url: null + }; + + this.aVOutput = { + name: null, + type: null, + enabled: null, + subtitleEnabled: null, + videoMode: null, + digitalAudioMode: null, + audioRange: null, + hdVideoFormat: null, + tvAspectRatio: null, + supportedVideoModes: null, + supportedDigitalAudioModes: null, + supportedAudioRanges: null, + supportedHdVideoFormats: null, + supportedAspectRatios: null, + current3DMode: null + }; + + this.signalInfo = { + strength: null, + quality: null, + ber: null, + snr: null, + lock: null + }; + + this.lNBInfo = { + lnbType: null, + lnbLowFreq: null, + lnbHighFreq: null, + crossoverFrequency: null, + lnbStartFrequency: null, + lnbStopFrequency: null, + orbitalPosition: null + }; + + this.tuner = { + id: null, + enableTuner: true, + signalInfo: new SignalInfo(this.signalInfo), + lnbInfo: new LNBInfo(this.lNBInfo), + frontEndPosition: null, + powerOnExternal: null + }; + + var idTypes = new IntegerCollection(12, 11); + var tunerTNT = new Tuner("TNT", idTypes, this.tuner); + var tuners = new TunerCollection(tunerTNT); + + var masterAVOutput = + new AVOutput("master", "both", true, this.aVOutput); + + var networkInterface = + new NetworkInterface("192.168.99.191", "6D:FF:29:E1:AF:33", true, true); + + this.localSystem = { + deviceID: undefined, + systemReady: false, + vendorName: null, + modelName: null, + familyName: null, + softwareVersion: null, + hardwareVersion: null, + serialNumber: null, + releaseVersion: null, + majorVersion: null, + minorVersion: null, + oipfProfile: null, + pvrEnabled: true, //This property is deprecated. + ciplusEnabled: false, + powerState: 1, + previousPowerState: 0, + timeCurrentPowerState: new Date().getTime(), + volume: 0, + mute: false, + tuners: tuners, + outputs: new AVOutputCollection(masterAVOutput), + networkInterfaces: new NetworkInterfaceCollection(networkInterface), + tvStandardsSupported: null, //Represented by a bitfield + tvStandard: configurationConstants.tvStandard.SECAM, + pvrSupport: 1, + startupInformation: null + }; + + } +}); + Modified: oipf/js/configuration/TestConfig.js =================================================================== --- oipf/js/configuration/TestConfig.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/configuration/TestConfig.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -13,15 +13,15 @@ var userAgent = navigator.userAgent; if (userAgent.includes("HbbTV") || userAgent.includes("SmartTv")) { + console.log("OIPF TESTS ON TV PLATFORM"); var hbbTv = ApplicationManager.getWindows[2]; hbbTv && hbbTv.deactivate(); var ui = ApplicationManager.getWindows()[0]; //or getWindowsByName ui && ui.keySet.setValue(0x10, []); !ui.visible && ui.show(); - !ui.active && ui.activate(); + ui.activate(); - var VideoBroadcastManager = VideoBroadcastTest.extend({ init: function() { @@ -130,46 +130,35 @@ var VideoBroadcastTest = VideoBroadcastManager.extend({ init: function() { -// this.superBeforeTest = VideoBroadcastTest.prototype.super.beforeTest; -// this.vidBroadManager = new VideoBroadcastManager(); - this.super.init(); -// this.onChangeState = this.super.beforeTest.bind(this); -// -// // beforeTest: function(resolve, reject) { -// // this.reject = reject.bind(null); -// // this.resolve = resolve.bind(null); -// // this.superBeforeTest.call(this, this.resolve, this.reject); -// // this.cancel = true; -// // }, -// -// this.beforeTest = this.super.beforeTest.bind(this); -// -// this.unrealizedToConnecting = this.super -// .unrealizedToConnecting.bind(this); -// -// this.connectingToPresenting = this.super -// .connectingToPresenting.bind(this); -// -// this.unrealizedToUnrealized = this.super. -// unrealizedToConnecting.bind(this); -// -// this.stopToStop = this.super.stopToStop.bind(this); -// -// this.noStatesDefined = this.super.noStatesDefined.bind(this); -// -// this.pushTransition = this.super.pushTransition.bind(this); -// -// this.pushTransitionWithError = this.super -// .pushTransitionWithError.bind(this); -// -// this.addTransition = this.super.addTransition.bind(this); -// -// this.addTransitionWithError = this.super -// .addTransitionWithError.bind(this); } }); + + var RecordingSchedulerTest = RecordingSchedulerTest.extend({ + + init: function() { + this.super.init(); + this.blocked = function() {}; + this.bindToCurrentChannel = this.blocked; + this.onChangeState = this.blocked; + this.createVideoBroadcast = function() { + if (!this.vidBroadObj) { + this.vidBroadObj = oipfObjectFactory.createVideoBroadcastObject(); + } + } + }, + + onPVREvent: function(resolve, reject, event) { + console.log("beforeTest"); + this.super.onPVREvent(resolve, reject, event.state, event.recording); + }, + + beforeTest: function(resolve, reject) { + console.log("beforeTest"); + this.super.beforeTest(resolve, reject); + } + + }); + } - - Modified: oipf/js/impl/CapabilitiesObject.js =================================================================== --- oipf/js/impl/CapabilitiesObject.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/CapabilitiesObject.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -1,7 +1,82 @@ +/* + * The OITF SHALL support following non-visual embedded object with + * the mime type 'application/oipfCapabilities'. + */ var CapabilitiesObject = Class.extend({ - - init : function(){ + /* + * Description: + * Returns the OITF’s capability description as an XML Document object using + * the syntax as defined in Annex F without using any namespace + * definitions. + * + * Visibility Type: readonly Document + */ + xmlCapabilities: null, + + /* + * Description: + * This property holds the number of possible additional decodes for + * SD video. Depending on the current usage of system resources this value + * may vary. The value of this property is likely to change if an HD video + * is started. + * + * Adding an A/V Control object or video/broadcast object may still fail, + * even if extraSDVideoDecodes is larger than 0. For A/V Control objects, + * in case of failure the play state for the A/V Control object shall be set + * to 6 ('error') with a detailed error code of 3 + * ('insufficient resources'). For video/broadcast objects, in case of + * failure the play state of the video/broadcast object shall be set to 0 + * ('unrealized') with a detailed error code of 11 + * ('insufficient resources'). + * + * Visibility Type: readonly Number + */ + extraSDVideoDecodes: null, + + /* + * Description: + * This property holds the number of possible additional decodes for + * HD video. Depending on the current usage of system resources this value + * may vary. The value of this property is likely to change if an SD video + * is started. + * + * Adding an A/V Control object or video/broadcast object may still fail, + * even if extraSDVideoDecodes is larger than 0. For A/V Control objects, + * in case of failure the play state for the A/V Control object shall be set + * to 6 ('error') with a detailed error code of 3 + * ('insufficient resources'). For video/broadcast objects, in case of + * failure the play state of the video/broadcast object shall be set to 0 + * ('unrealized') with a detailed error code of 11 + * ('insufficient resources'). + * + * Visibility Type: readonly Number + */ + extraHDVideoDecodes: null, + + + init: function(modelFactory) { + this.xmlParser = modelFactory.getXmlParser(); + this._defaultCapabilities = modelFactory.getCapabilitiesProperties(); + this.xmlCapabilities = this.xmlParser + .getXmlDocument(this._defaultCapabilities); + }, + + /* + * Description: + * Check if the OITF supports the passed capability. + * Returns true if the OITF supports the passed capability, false otherwise. + * + * Arguments: + * - profileName: + * An OIPF base UI profile string or a UI Profile name fragment string as + * defined in section 9.2. + * Examples of valid profileName: “ OITF_HD_UIPROF ” or “ +PVR ”. + * + * Return: Boolean + */ + hasCapability: function(profileName) { + return this._defaultCapabilities.hasCapablity(profileName); } }); \ No newline at end of file Modified: oipf/js/impl/ConfigurationObject.js =================================================================== --- oipf/js/impl/ConfigurationObject.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/ConfigurationObject.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -24,24 +24,21 @@ init : function(){ this._listeners = {}; this._callbacks = {}; + var configDefaultProperties = new ConfigDefaultProperties(); this._eventManager = new EventManager(); - var idTypes = new IntegerCollection(12,11); - var tunerTNT = new Tuner(idTypes); - var tuners = new TunerCollection(tunerTNT); - var masterOutput = new AVOutput("master", "both", true); - var outputs = new AVOutputCollection(masterOutput); - this.localSystem = new LocalSystem(tuners, outputs); - this.configuration = new Configuration(); + this.localSystem = new LocalSystem(configDefaultProperties); + this.configuration = + new Configuration(configDefaultProperties.configuration); }, _getCallback : function(type) { - if(this._callbacks) { + if (this._callbacks) { return this._callbacks[type]; } }, - _setCallback: function(type, callback){ - if(this._callbacks) { + _setCallback: function(type, callback) { + if (this._callbacks) { this._callbacks[type] = callback; } }, Modified: oipf/js/impl/RecordingSchedulerObject.js =================================================================== --- oipf/js/impl/RecordingSchedulerObject.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/RecordingSchedulerObject.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -21,50 +21,234 @@ */ discInfo: null, - init: function() { - this.eventMnager = new EventManager(); - this.timerManager = new TimerManager(); - this._timeout = this.timermanager.createTimer; - this.callbacks = {}; - this.listeners = {}; - + /* + * FIXME: + * Yannis - 29/014/2015 - Use of a utils class in future to manage 'Date' + * object. + */ + init: function(subConfiguration, modelFactory, dateUtils) { + this._dateUtils = dateUtils; + this._modelFactory = modelFactory; + this.SCHEDULED = recordingConstants.state.SCHEDULED; + this.STARTED = recordingConstants.state.STARTED; + this.COMPLETED = recordingConstants.state.COMPLETED; + this.REMOVED = recordingConstants.state.REMOVED; + this.UPDATED = recordingConstants.state.UPDATED; + this.BEFORE_STARTED = recordingConstants.state.BEFORE_STARTED; + this._subConfiguration = subConfiguration; + this._eventManager = new EventManager(); + this._timerManager = new TimerManager(); + this._timeout = this._timerManager.createTimer.bind(this._timerManager); + this._timerManagerRecording = new TimerRecordingManager(); + this._timeoutRecording = this._timerManagerRecording + .createTimer.bind(this._timerManagerRecording); + this._callbacks = {}; + this._listeners = {}; + /* + * Description: + * Contain the ojects of type Recording in-progress and completed. + * Actually only one recording will be authorized. + */ + this._recordings = {}; this.recordings = new ScheduledRecordingCollection(); + this.discInfo = null; }, /* - *Description: + * Description: * * FIXME: * Yannis - 27/04/2015 - Do verification on parameter * Yannis - 27/04/2015 - Verify pvr capability in order to manage - * recordings in order to store them into properties "recordings". + * recordings to store them into properties "recordings". + * Yannis - 27/04/2015 - Verify parental control settings about recording + * right. + * */ - record: function(programme) { - return new ScheduledRecording(programme); + record: function() { + var parameters = arguments; + if (parameters.length == 1) { + var scheduledRecording = new ScheduledRecording(parameters[0]); + } else if (parameters.length == 4) { + scheduledRecording = new ScheduledRecording(parameters[0], + parameters[1], + parameters[2], + parameters[3]); + } else { + return null; + } + + scheduledRecording.startPadding = this._subConfiguration.pvrStartPadding; + scheduledRecording.endPadding = this._subConfiguration.pvrEndPadding; + + if (this._recordingConflict(scheduledRecording)) { + return null; + } + + this._fireEventScheduled(scheduledRecording); + + var recording = this._createRecording(scheduledRecording); + this._recordings[recording.id] = recording; + this.recordings.push(recording); + + this._planifyStartRecording(recording) + .then(this._planifyEndRecording.bind(this, recording)); + + return recording; }, /* * Description: * * FIXME: - * Yannis - 27/04/2015 - Do verification on parameters - * Yannis - 27/04/2015 - Verify pvr capability in order to manage - * recordings in order to store them into properties "recordings". + * Yannis - 27/04/2015 - Do verification on parameters. + * Yannis - 27/04/2015 - Verify pvr capability in order to know + * if this properties "recordings" can be used. + * Yannis - 27/04/2015 - Verify parental control settings about recording + * right. */ recordAt: function(startTime, duration, repeatDays, channelID) { - var channel = this.getChannelConfig().channelList.getChannel(channelID); + this.record(startTime, duration, repeatDays, channelID); + }, + + /* + * + * @param {ScheduledRecording} recording + * @returns {undefined} + */ + remove: function(recording) { + if (recording) { + this._timerManagerRecording.clearTimer(recording.id); + this.recordings.splice(this.recordings.indexOf(recording), 1); + delete this._recordings[recording.id]; + + this._timeoutRecording() + .then(this._fireEventRemoved.bind(this, recording)); + + return; + } + console.log("The recording can't be remove."); + }, + + /* + * Description: + * Returns a subset of all the recordings that are scheduled but which have + * not yet started. The subset SHALL include only scheduled recordings that + * were scheduled using a service from the same FQDN as the domain of the + * service that calls the method. + * + * @returns { ScheduledRecordingCollection} + */ + getScheduledRecordings: function() { + if (this.recordings) { + return this.recordings; + } + }, + + /* + * Description: + * Returns the channel line-up of the OITF in the form of a ChannelConfig + * object as defined in section 7.13.9. The ChannelConfig object returned + * from this function SHALL be identical to the ChannelConfig object + * returned from the getChannelConfig() method on the video/broadcast object + * as defined in section 7.13.1.3. + * + * @returns {ChannelConfig} + */ + getChannelConfig: function() { + return oipfObjectFactory.createChannelConfig(); + }, + + createProgrammeObject: function() { - if (channel) { - return new ScheduledRecording( - startTime, duration, repeatDays, channel); + }, + + /* + * Description: + * Returns the Recording object for which the value of the Recording.id + * property corresponds to the given id parameter. If such a Recording does + * not exist, the method returns null. + * + * Arguments: + * - id: Identifier corresponding to the id property of a Recording object. + * + * @returns {Recording} + */ + getRecording: function(id) { + return this._recordings[id] || null; + }, + + /* + * Description: + * Stop an in-progress recording. The recording SHALL NOT be deleted. + * + * Arguments: + * - recording: The recording to be stopped. + * + * @returns {undefined} + */ + stop: function(recording) { + console.log("Method stop called"); + if (recording && recording.state == this.STARTED) { + this._timerManagerRecording.clearTimer(recording.id); + return; } + console.log("The recording can't be stop."); + }, + + /* + * Description: + * Update the recordings property to show the current status of all + * recordings. + * + * @returns {undefined} + */ + refresh: function() { - return null; }, - getChannelConfig: function() { + /* + * Description: + * For scheduled recordings the properties startTime, duration and + * repeatDays can be modified. For ongoing recordings only the duration + * property may be modified. This method SHALL return true if the operation + * succeeded, or false if for any reason it rescheduling is not possible + * (e.g. the updated recording overlaps with another scheduled recording and + * there are insufficient system resources to do both). If the method + * returns false then no changes SHALL be made to the recording. + * + * Arguments: + * - id: The id of the recording to update. + * - startTime: The new start time of the recording, or undefined if the + * start time is not to be updated. + * - duration: The new duration of the recording, or undefined if the + * duration is not to be updated. + * - repeatDays: The new set of days on which the recording is to be + * repeated, or undefined if this is not to be updated. + * + * @returns {undefined} + */ + update: function(id, startTime, duration, repeatDays) { + var recording = this._recordings[id]; + if (!recording) { + return false; + } + + if (recording.state == this.STARTED) { + if (duration) { + return this._updateDuration(id, duration); + } + + } else if (recording.state == this.SCHEDULED) { + startTime && recording._setStartTime(startTime); + duration && recording._setDuration(duration); + repeatDays && (recording.repeatDays = repeatDays); + + } + + return false; }, get onPVREvent() { @@ -81,7 +265,7 @@ } }, - _setCallback: function(type, callback){ + _setCallback: function(type, callback) { if(this._callbacks) { this._callbacks[type] = callback; } @@ -91,12 +275,299 @@ this._eventManager.addEventListener(type, listener, this); }, - _fireEvent: function(event) { + _fireEvent: function(state, recording) { + var event = createCustomEvent("PVREvent", [state, recording]); this._eventManager.fireEvent(event, this); }, + _fireEventScheduled: function(recording) { + this._fireEvent(this.SCHEDULED, recording); + }, + + _fireEventBeforeStarted: function(recording) { + this._fireEvent(this.BEFORE_STARTED, recording); + }, + + _fireEventStarted: function(recording) { + this._fireEvent(this.STARTED, recording); + }, + + _fireEventCompleted: function(recording) { + this._fireEvent(this.COMPLETED, recording); + }, + + _fireEventUpdated: function(recording) { + this._fireEvent(this.UPDATED, recording); + }, + + _fireEventRemoved: function(recording) { + this._fireEvent(this.REMOVED, recording); + }, + removeEventListener: function(type, listener) { this._eventManager.removeEventListener(type, listener, this); + }, + + _recordingConflict: function(recording) { + + if (this._isProgrammeFinished(recording)) { + return true; + } + + for (var i = 0, l = this.recordings.length; i < l; i++) { + + var startPadding = this.recordings[i].startPadding; + var endPadding = this.recordings[i].endPadding; + var currentStartTime = this.recordings[i].startTime + startPadding; + var currentDuration = this.recordings[i].duration + endPadding; + var currentStopTime = currentStartTime + currentDuration; + + var recordingStartTime = recording.startTime + recording.startPadding; + var recordingStopTime = recordingStartTime + recording.duration + + recording.endPadding; + + /* + * First, verify that two recordings won't schedules at same time. + * Second, verify that two recordings don't overlap. + */ + if (currentStartTime == recordingStartTime || + (recordingStartTime >= currentStartTime && + recordingStartTime <= currentStopTime) || + (recordingStopTime >= currentStartTime && + recordingStopTime <= currentStopTime)) { + + return true; + } + } + return false; + }, + + _createRecording: function(recording) { + return new Recording(recording); + }, + + /* + * FIXME: + * Yannis - 29/04/2015 - Management of negative padding. + * Yannis - 29/04/2015 - Modify recordingStartTime of concerned recording. + */ + _planifyStartRecording: function(recording) { + if(this._isProgrammeStarted(recording)) { + + var timer = this._dispatchBeforeStartedEventAndStartedEvent(null, recording); + console.log("The recording start now because the programme already had started."); + + } else { + + var timeToStart = this._getDurationFromNowToSpecificTime(recording.startTime + + recording.startPadding); + + console.log("The recording will start in", + this._dateUtils.secondsToMinutes(timeToStart), "minutes."); + + this._dispatchBeforeStartedEventAndStartedEvent( + this._dateUtils.secondsToMilliseconds(timeToStart), + recording); + + } + + this._timerManagerRecording + .recordingTimers[recording.id] = { + "start": timer, + "end": null + }; + + return timer; + }, + + /* + * FIXME: + * Yannis - 29/04/2015 - Managing of negative padding. + * Yannis - 29/04/2015 - Modify recordingEndTime of concerned recording. + */ + _planifyEndRecording: function(recording) { + var timeToEnd = this._getDurationFromNowToSpecificTime(recording.startTime + + recording.duration + recording.endPadding); + + var timer = this._timeoutRecording(this._dateUtils.secondsToMilliseconds(timeToEnd)) + .then(recording._setState.bind(recording, this.COMPLETED)) + .then(this._fireEventCompleted.bind(this, recording)); + + console.log("The recording will end in", + this._dateUtils.secondsToMinutes(timeToEnd), + "minutes after its starting."); + + this._timerManagerRecording + .recordingTimers[recording.id].end = timer; + + return timer; + }, + + _isProgrammeStarted: function(recording) { + var startTime = recording.startTime; + var endTime = startTime + recording.duration; + + var currentTime = this._dateUtils.nowInSeconds(); + + return (currentTime >= startTime && currentTime <= endTime); + }, + + /* + * Description : + * Avoid schedule recording whose the programme already has been broadcasted. + * + * Return: Boolean + */ + _isProgrammeFinished: function(recording) { + var startTime = recording.startTime; + var endTime = startTime + recording.duration; + + var currentTime = this._dateUtils.nowInSeconds(); + + return (endTime <= currentTime); + }, + + _getDurationFromNowToSpecificTime: function(time) { + return time - this._dateUtils.nowInSeconds(); + }, + + _updateDuration: function(id, duration) { + console.log("Try updating duration"); + var recording = this._recordings[id]; + + if (!recording) { + return false; + } + + var newStopTime = recording.startTime + duration + recording.endPadding; + + if (newStopTime <= this._dateUtils.nowInSeconds()) { + return false; + } + + var recordings = this.recordings.filter(function(recording) { + return recording.id != id; + }); + + + for (var i = 0, l = recordings.length; i < l; i++) { + var startPadding = recordings[i].startPadding; + var endPadding = recordings[i].endPadding; + var currentStartTime = recordings[i].startTime + startPadding; + var currentDuration = recordings[i].duration + endPadding; + var currentStopTime = currentStartTime + currentDuration; + + /* + * First, verify that two recordings won't schedules at same time. + * Second, verify that two recordings don't overlap. + */ + if (newStopTime >= currentStartTime) { + + return false; + } + } + recording._setDuration(duration); + + this._timerManagerRecording.clearTimer(recording.id); + + this._planifyEndRecording(recording); + + return true; + + }, + + _updateFields: function(id, startTime, duration, repeatDays) { + console.log("Try updating duration"); + var recording = this._recordings[id]; + + if (!recording || (!startTime && !duration && !repeatDays)) { + return false; + } + + if (startTime) { + var recordingStartTime = startTime + recording.startPadding; + var recordingStopTime = recordingStartTime + recording.duration + + recording.endPadding; + } + + if (duration && startTime) { + var recordingStopTime = recordingStartTime + duration + + recording.endPadding; + } else if (duration && !startTime) { + var recordingStopTime = recording.startTime + recording.duration + + recording.endPadding; + } + + if (recordingStartTime <= this._dateUtils.nowInSeconds() || + recordingStopTime <= this._dateUtils.nowInSeconds()) { + return false; + } + + var recordings = this.recordings.filter(function(recording) { + return recording.id != id; + }); + + for (var i = 0, l = recordings.length; i < l; i++) { + var startPadding = recordings[i].startPadding; + var endPadding = recordings[i].endPadding; + var currentStartTime = recordings[i].startTime + startPadding; + var currentDuration = recordings[i].duration + endPadding; + var currentStopTime = currentStartTime + currentDuration; + + /* + * First, verify that two recordings won't schedules at same time. + * Second, verify that two recordings don't overlap. + */ + if (recordingStartTime == currentStartTime || + (recordingStartTime >= currentStartTime && + recordingStartTime <= currentStopTime) || + (recordingStopTime >= currentStartTime && + recordingStopTime <= currentStopTime)) { + + return false; + } + } + + repeatDays && recording._setRepeatDays(repeatDays); + + if (startTime) { + this._timerManagerRecording.clearTimer(recording.id); + startTime && recording._setStartTime(startTime); + + this._planifyStartRecording(recording) + .then(this._planifyEndRecording.bind(this, recording)); + + this._timeoutRecording() + .then(this._fireEventUpdated.bind(this, recording)); + + return true; + + } + + if (duration) { + this._timerManagerRecording.clearTimer(recording.id); + duration && recording._setDuration(duration); + + this._planifyEndRecording(recording); + + this._timeoutRecording() + .then(this._fireEventUpdated.bind(this, recording)); + + return true; + + } + + return false; + }, + + _dispatchBeforeStartedEventAndStartedEvent: function(timer, recording) { + return this._timeoutRecording(timer) + .then(recording._setState.bind(recording, + this.BEFORE_STARTED)) + .then(this._fireEventBeforeStarted.bind(this, recording)) + .then(recording._setState.bind(recording, + this.STARTED)) + .then(this._fireEventStarted.bind(this, recording)); } - + }); \ No newline at end of file Modified: oipf/js/impl/model/Channel.js =================================================================== --- oipf/js/impl/model/Channel.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/Channel.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -123,7 +123,7 @@ init: function () { var dispatcher = { 3: "_createChannelATSC_T", 4: "_createChannelDVB_SI_DIRECT", 5: "_createChannelDVBOrISDB", 6: "_createChannelIPTV"}; - this.channelId = createUUID(); + (arguments.length != 6) && this._setCcid(createUUID()); this[dispatcher[arguments.length]].apply(this, arguments); }, @@ -158,6 +158,10 @@ this.dsd = dsd; this.sid = sid; this.name = name; + }, + + _setCcid: function(ccid) { + this.ccid = ccid.toString(); } }); \ No newline at end of file Modified: oipf/js/impl/model/Configuration.js =================================================================== --- oipf/js/impl/model/Configuration.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/Configuration.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -1,19 +1,5 @@ var Configuration = Class.extend({ - defaultProperties: { - preferredAudioLanguage: "fra", - preferredSubtitleLanguage: "fra", - preferredUILanguage: "fra", - countryId: "FRA", - regionId: 0, - pvrPolicy: configurationConstants.pvrPolicy.WATCHED_RECORDINGS, - pvrSaveEpisodes: 5, - pvrSaveDays: 15, - pvrStartPadding: 300, //Measured in (s) - pvrEndPadding: 300, //Measured in (s) - preferredTimeShiftMode: videoBrodcastConstants.timeShiftMode.OFF - }, - /* * Description: * A comma-separated set of languages to be used for audio playback, in order of preference. Each language SHALL be indicated by its ISO 639-2 language code as * defined in [ISO 639-2]. @@ -135,11 +121,8 @@ */ preferredTimeShiftMode: null, - init: function() { - var keys = Object.keys(this.defaultProperties); - for (var i = 0, l = keys.length; i < l; i++) { - this[keys[i]] = this.defaultProperties[keys[i]]; - } + init: function(defaultProperties) { + oipf.utils.initProperties.call(this, defaultProperties); this._keys = {}; }, Modified: oipf/js/impl/model/IntegerCollection.js =================================================================== --- oipf/js/impl/model/IntegerCollection.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/IntegerCollection.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -4,9 +4,9 @@ * */ -var IntegerCollection = Array.extend({ +var IntegerCollection = Collection.extend({ init: function() { - this.push.apply(this, arguments); + this.super.init.apply(this, arguments); } }); Modified: oipf/js/impl/model/LocalSystem.js =================================================================== --- oipf/js/impl/model/LocalSystem.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/LocalSystem.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -7,7 +7,257 @@ var LocalSystem = Class.extend({ /* + * The OITF is in the off state and no power is consumed. + * This is the case of a power outage or if the OITF has the + * ability to be completely turned off. Scheduled recording is + * not expected to work. + */ + OFF: 0, + + /* + * The OITF is in normal working mode with user + * interaction. The DAE applications may render any + * presentation graphically. + */ + ON: 1, + + /* + * The OITF is in the lowest possible power consumption + * state (meeting regulations and certifications). The OITF + * may support wake-up from a passive standby in order, for + * example, to perform a scheduled recording. + */ + PASSIVE_STANDBY: 2, + + /* + * The OITF is in an intermediate power consumption state. + * The output to the display shall be inactive. In this state + * DAE applications may continue to operate. + */ + ACTIVE_STANDBY: 3, + + /* + * The OITF is in the lowest possible power consumption + * state (meeting regulations and certifications). If th + * platform supports hibernate mode then the OITF stores + * all applications in volatile memory to allow for quick + * startup. + */ + PASSIVE_STANDBY_HIBERNATE: 4, + + /* + * The OITF shall restart and return to a ON state. + */ + RESTART: 5, + + /* + * Restart the OITF and reset all settings and data to an + * initial/factory state. The exact settings and data to be + * reset are implementation dependant. The use of the this + * operation with the setPowerState method is subject to + * security control defined in section 10.1.3.8 + */ + FACTORY_RESET: 6, + + /* + * No startup URL is known. + */ + STARTUP_URL_NONE: 0, + + /* + * The startup URL is derived from DHCP procedures. + */ + STARTUP_URL_DHCP: 1, + + /* + * The startup URL is derived through TR-069 procedures. + */ + STARTUP_URL_TR069: 2, + + /* + * The startup URL is that which is configured through the OITF firmware. + */ + STARTUP_URL_PRECONFIGURED: 3, + + /* + * The startup URL is obtained through other + * (perhaps non-standardized) procedures. + */ + STARTUP_URL_OTHER: 9, + + /* * Description: + * Private OITF Identifier. This property SHALL take the value undefined + * except when accessed by applications meeting + * either of the following criteria: + * + * - The application is signalled in an SD&S service provider discovery + * record with an application usage of + * urn:oipf:cs:ApplicationUsageCS:2009:hni-igi where + * the SD&S service provider discovery record was obtained by + * the OITF through the procedure defined in section 5.4.1.2 of [OIPF_PROT2]. + * + * - The URL of the application was discovered directly through + * the procedure defined in section 5.4.1.2 of [OIPF_PROT2]. + * + * In these two cases, it SHALL take the same value as defined for the + * DHCP client identifier in DHCP option 61 + * in section 12.1.1.1 of [OIPF_PROT2]. + * + * Visibility Type: readonly String + */ + deviceID: undefined, + + /* + * Description: + * Indicates whether the system has finished initialising. + * A value of true indicates that the system is ready. + * + * Visibility Type: readonly Boolean + */ + systemReady: null, + + /* + * Description: + * String identifying the vendor name of the device. + * + * Visibility Type: readonly String + */ + vendorName: null, + + /* + * Description: + * String identifying the model name of the device. + * + * Visibility Type: readonly String + */ + modelName: null, + + /* + * Description: + * String identifying the name of the family that the device belongs to. + * Devices in a family differ only by details that do not impact + * the behaviour of the OITF aspect of the device, e.g. screen size, + * remote control, number of HDMI ports, size of hard disc. + * Family names are allocated by the vendor and the combination of + * vendorName and familyName should uniquely identify a family of devices. + * Different vendors may use the same familyName, although + * they are recommended to use conventions that avoid this. + * + * Visibility Type: readonly String + */ + familyName: null, + + /* + * Description: + * String identifying the version number of the platform firmware. + * + * Visibility Type: readonly String + */ + softwareVersion: null, + + /* + * Description: + * String identifying the version number of the platform firmware. + * + * Visibility Type: readonly String + */ + hardwareVersion: null, + + /* + * Description: + * String identifying the version number of the platform firmware. + * + * Visibility Type: readonly String + */ + serialNumber: null, + + /* + * Description: + * Release version of the OIPF specification implemented by the OITF. + * For instance, if the OITF implements release 2 version “1.0”, + * this property should be set to 2. + * + * Visibility Type: readonly Integer + */ + releaseVersion: null, + + /* + * Description: + * Major version of the OIPF specification implemented by the OITF. + * For instance, if the OITF implements release 2 version “2.0”, + * this property should be set to 2. + * + * Visibility Type: readonly Integer + */ + majorVersion: null, + + /* + * Description: + * Minor version of the OIPF specification implemented by the OITF. + * For instance, if the OITF implements release 2 version “2.0”, + * this property should be set to 0. + * + * Visibility Type: readonly Integer + */ + minorVersion: null, + + /* + * Description: + * Profile of the OIPF specification implemented by the OITF. + * Values of this field are not defined in this specification. + * + * Visibility Type: readonly String + */ + oipfProfile: null, + + /* + * Description: + * Flag indicating whether the platform has PVR capability (local PVR). + * Note: This property is deprecated in favour of the pvrSupport property. + * + * Visibility Type: readonly Boolean + */ + pvrEnabled: null, + + /* + * Description: + * Flag indicating whether the platform has CI+ capability. + * + * Visibility Type: readonly String + */ + ciplusEnabled: Boolean, + + /* + * Description: + * The powerState property provides the DAE application the ability + * to determine the current state of the OITF. + * The property is limited to the ACTIVE_STANDBY or ON states. + * + * Visibility Type: readonly Integer + */ + powerState: null, + + /* + * Description: + * The previousPowerState property provides the DAE application the ability + * to retrieve the previous state. + * + * Visibility Type: readonly String + */ + previousPowerState: null, + + /* + * Description: + * The time that the OITF entered the current power state. + * The time is represented in seconds since midnight (GMT) on 1/1/1970. + * + * Visibility Type: readonly String + */ + timeCurrentPowerState: null, + + /* + * Description: * Get or set the overall system volume. Valid values for this property are in the range 0 - 100. The OITF SHALL store this setting persistently. * * Type: Integer @@ -37,11 +287,390 @@ * * Visibility Type: readonly AVOutputCollection */ - outputs: null, + outputs: null, - init: function(tuners, outputs) { - this.tuners = tuners; - this.outputs = outputs; + /* + * Description: + * A collection of NetworkInterface objects representing + * the available network interfaces. + * + * Visibility Type: readonly NetworkInterfaceCollection + */ + networkInterfaces: null, + + /* + * Description: + * Read whether the display is currently in a 2D or 3D mode. + * Return values are: + * ------------------------------------------------------------------------ + * Value | Description + * ------------- ---------------------------------------------------------- + * 1 | Indicates platform support for the NTSC TV standard. + * ------------- ---------------------------------------------------------- + * 2 | Indicates platform support for the PAL-BGH TV standard. + * ------------- ---------------------------------------------------------- + * 4 | Indicates platform support for the SECAM TV standard. + * ------------- ---------------------------------------------------------- + * 8 | Indicates platform support for the PAL-M TV standard. + * ------------- ---------------------------------------------------------- + * 16 | Indicates platform support for the PAL-N TV standard. + * ------------------------------------------------------------------------ + * Values are stored as a bitfield. + * + * Visibility Type: Integer + */ + tvStandardsSupported: null, + + /* + * Description: + * Get the TV standard for which the analogue video outputs are currently + * configured. This property can take one or more of the following values: + * ------------------------------------------------------------------------ + * Value | Description + * ------------- ---------------------------------------------------------- + * 0 | Indicates there are no analogue video outputs + * ------------- ---------------------------------------------------------- + * 1 | Indicates platform support for the NTSC TV standard. + * ------------- ---------------------------------------------------------- + * 2 | Indicates platform support for the PAL-BGH TV standard. + * ------------- ---------------------------------------------------------- + * 4 | Indicates platform support for the SECAM TV standard. + * ------------- ---------------------------------------------------------- + * 8 | Indicates platform support for the PAL-M TV standard. + * ------------- ---------------------------------------------------------- + * 16 | Indicates platform support for the PAL-N TV standard. + * ------------------------------------------------------------------------ + * + * Visibility Type: Integer + */ + tvStandard: null, + + /* + * Description: + * Flag indicating the type of PVR support used by the application. + * This property may take zero or more of the following values: + * ------------------------------------------------------------------------ + * Value | Description + * ------------- ---------------------------------------------------------- + * | PVR functionality is not supported. This is the default + * 0 | value if <recording> as specified in section 9.3.3 + * | has value false . + * ------------- ---------------------------------------------------------- + * | PVR functionality is not supported. This is the default + * 1 | value if <recording> as specified in section 9.3.3 + * | has value false . + * ------------- ---------------------------------------------------------- + * + * Visibility Type: readonly Integer + */ + pvrSupport: null, + + /* + * Description: + * A collection of NetworkInterface objects representing + * the available network interfaces. + * + * Visibility Type: readonly NetworkInterfaceCollection + */ + startupInformation: null, + + init: function(defaultProperties) { + this._listeners = {}; + this._callbacks = {}; + this._eventManager = new EventManager(); + this._timerManager = new TimerManager(); + this._timeout = this._timerManager.createTimer; + this._defaultProperties = defaultProperties; + oipf.utils.initProperties.call(this, defaultProperties.localSystem); + this.systemReady = true; + }, + + /* + * Description: + * Set the resolution of the graphics plane. If the specified resolution + * is not supported by the OITF, this method SHALL return false. + * Otherwise, this method SHALL return true. + * + * Arguments: + * - width: The width of the display, in pixels. + * + * - height: The height of the display, in pixels. + * + * Return: Boolean + */ + setScreenSize: function(width, height) { + var parameters = arguments; + + if (parameters.length > 2) { + throw new TypeError("Excessive number of arguments."); + } + + if (parameters.length < 2) { + throw new TypeError("Insufficient number of arguments."); + } + + if (!Number.isInteger(width) && !Number.isInteger(height)) { + throw new TypeError + ("This function cannot be called with theses arguments."); + } + + var authorizedResolution = + this._defaultProperties.screenSize[width+"x"+height]; + + if (authorizedResolution) { + this._width = width; + this._height = height; + + return true; + } + + return false; + + }, + + /* + * Description: + * Set the TV standard to be used on the analogue video outputs. + * Returns false if the requested mode cannot be set. + * + * Arguments: + * - tvStandard: The TV standard to be set. + * Valid values are defined in the description of the + * tvStandard property in section 7.3.3.2. + * + * Return: Boolean + * FIXME: Yannis - 23/04/2015 - Take intp account that the value of + * "tvStandard" can be stored as a bitfield. + */ + setTVStandard: function(tvStandard) { + var parameters = arguments; + + if (parameters.length > 1) { + throw new TypeError("Excessive number of arguments."); + } + + if (parameters.length < 1) { + throw new TypeError("Insufficient number of arguments."); + } + + if (!Number.isInteger(arguments[0])) { + throw new TypeError + ("This function cannot be called with theses arguments."); + } + + var tvStandardSupported = + this._defaultProperties.tvStandardsSupported[tvStandard]; + + if (tvStandardSupported) { + this.tvStandard = tvStandard; + return true; + } + + return false; + }, + + /* + * Description: + * Set the type of PVR support used by the application. + * The types of PVR supported by the receiver MAY not be supported + * by the application; in this case, the return value indicates + * the pvr support that has been set. + * + * Arguments: + * - state: The type of PVR support desired by the application. + * More than one type of PVR functionality MAY be specified, + * allowing the receiver to automatically select the + * appropriate mechanism. Valid values are: + * + * - height: The height of the display, in pixels. + * + * Return: Boolean + */ + setPvrSupport: function(state) { + var parameters = arguments; + + if (parameters.length > 1) { + throw new TypeError("Excessive number of arguments."); + } + + if (parameters.length < 1) { + throw new TypeError("Insufficient number of arguments."); + } + + if (!Number.isInteger(state)) { + throw new TypeError + ("This function cannot be called with theses arguments."); + } + + if (state == 0 || state == 1) { + this.pvrSupport = state; + return true; + } else { + this.pvrSupport = 0; + return this.pvrSupport; + } + + }, + + /* + * Description: + * The setPowerState() method allows the DAE application to + * modify the OITF state. The power state change may be restricted + * for some values of type, for example OFF, PASSIVE_STANDBY, + * RESTART and FACTORY_RESET . A call to setPowerState() with a + * restricted value of type SHALL return false . + * + * Arguments: + * - type: The type values that may be specified are defined + * in section 7.3.3.1 + * + * Return: Boolean + */ + setPowerState: function(type) { + var parameters = arguments; + + if (parameters.length > 1) { + throw new TypeError("Excessive number of arguments."); + } + + if (parameters.length < 1) { + throw new TypeError("Insufficient number of arguments."); + } + + if (!Number.isInteger(arguments[0])) { + throw new TypeError + ("This function cannot be called with theses arguments."); + } + + var restrictedPowerState = + this._defaultProperties.restrictedPowerState[type]; + + if (restrictedPowerState) { + return false; + } else { + this.previousPowerState = this.powerState; + this.timeCurrentPowerState = new Date().getTime(); + this.powerState = type; + this._timeout() + .then(this._fireEvent.bind( + this, createCustomEvent("PowerStateChange", [this.powerState]))); + + return true; + } + + }, + + /* + * Description: + * Set the credentials for the specified protocol to use for digest a + * uthentication negotiation for all subsequent requests to the specified + * domain. The credentials are persistently stored overwriting any previous + * set credentials. If domain is null the provided credentials SHALL apply + * for all domains. Returns true if credentials are successfully set, + * false otherwise. + * If digest authentication is not supported for + * the specified protocol then return false . The valid values are + * the strings “ http ” and “ https ”. + * Setting of Digest Credentials on the same protocol and domain + * SHALL update the username and password. + * If the credentials, when used, are incorrect then the behaviour + * SHALL be the same as any other time that stored credentials + * are incorrect, e.g. saved values from a user prompt. + * The credentials SHALL be used (if necessary) in all requests + * made by DAE applications. The credentials MAY be used in requests + * made by other components such as media players, DLNA clients, etc. + * + * Arguments: + * - protocol: The protocol to apply the credentials. + * + * - domain: The domain to which the credentials apply. + * + * - username: The username to be used in the digest authentication. + * + * - password: The password to be used in the digest authentication. + * + * Return: Boolean + */ + setDigestCredentials: function(protocol, domain, username, password ) { + if (protocol != "https" && protocol != "http") { + throw new Error("Invalid protocol."); + } +// Utiliser le localStorage pour stocker les information sionon utilisation d'un fichier simplement + }, + + /* + * Description: + * Clear any previously set digest credentials for the specified domain. + * If domain is null all set credentials are cleared. + * Returns true if the digest credentials for the given protocol and + * domain were cleared or do not exist, + * or false if credentials failed to be cleared. + * + * Arguments: + * - protocol: The protocol to apply the credentials. The value should + * be the same as one of those specified for + * the setDigestCredentials() method. + * + * - domain: The domain to which the credentials apply. + + * + * Return: Boolean + */ + clearDigestCredentials: function(protocol, domain, username, password) { + + }, + + /* + * Description: + * Check if digest credentials are currently defined + * for the specified protocol and domain. + * Returns true if credentials have been set by a previous call to + * setDigestCredentials() , otherwise returns false . + * + * Arguments: + * - protocol: The protocol to apply the credentials. + * The value should be the same as one of those specified for + * the setDigestCredentials() method. + * + * - domain: The domain to which the credentials apply. + * + * Return: Boolean + */ + hasDigestCredentials: function(protocol, domain, username, password) { + + }, + + get onPowerStateChange() { + return this._getCallback("PowerStateChange"); + }, + + set onPowerStateChange(callback) { + this._setCallback("PowerStateChange", callback); + }, + + _getCallback : function(type) { + if(this._callbacks) { + return this._callbacks[type]; + } + }, + + _setCallback: function(type, callback){ + if(this._callbacks) { + this._callbacks[type] = callback; + } + }, + + addEventListener: function(type, listener) { + this._eventManager.addEventListener(type, listener, this); + }, + + _fireEvent: function(event) { + this._eventManager.fireEvent(event, this); + }, + + removeEventListener: function(type, listener) { + this._eventManager.removeEventListener(type, listener, this); } + }); \ No newline at end of file Modified: oipf/js/impl/model/MetadataSearch.js =================================================================== --- oipf/js/impl/model/MetadataSearch.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/MetadataSearch.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -140,7 +140,7 @@ this._ordering = []; this._fireEventModified = this._searchManager - ._fireEventModified.bind(this._searchManager); + ._fireEventModified.bind(this._searchManager); }, Modified: oipf/js/impl/model/ModelFactory.js =================================================================== --- oipf/js/impl/model/ModelFactory.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/ModelFactory.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -12,6 +12,7 @@ this.xmlTvData = null; this.createXmlTvData(); this.createMetadataManager(); + this.capabilitiesProperties = new CapabilitiesProperties(); }, createXmlTvData: function() { @@ -83,6 +84,10 @@ setProperty: function(propertyName, value) { console.log("Method setProperty"); this[propertyName] = value; + }, + + getCapabilitiesProperties: function() { + return this.capabilitiesProperties; } }); Modified: oipf/js/impl/model/Programme.js =================================================================== --- oipf/js/impl/model/Programme.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/Programme.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -322,22 +322,22 @@ */ recording: null, - init: function(name, startTime, duration, description, episode, channel, blocked) { - this.name = name; - this.startTime = startTime; - this.duration = duration; - this.description = description; - this.episode = episode; - this.channel = channel; - this.blocked = blocked; + /* + * FIXME: + * Yannis - 30/04/2015 - The properties initialized here must be disappear + * in future. + * + * @param {Object} initObject + * @returns {undefined} + */ + init: function(initObject) { + oipf.utils.initProperties.call(this, initObject); + this.blocked = null; this.longName = null; - this.description = null; this.longDescription = null; - this.duration = null; this.channelID = null; this.totalEpisodes = null; this.is3D = null; - this.programmeID = null; this.programmeIDType = null; this.IMI = null; this.parentalRatings = null; Added: oipf/js/impl/model/Recording.js =================================================================== --- oipf/js/impl/model/Recording.js (rev 0) +++ oipf/js/impl/model/Recording.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,75 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var Recording = ScheduledRecording.extend({ + + uri: null, + id: null, + doNotDelete: null, + saveDays: null, + saveEpisodes: null, + blocked: null, + showType: null, + subtitles: null, + + /* + * Decsription: + * + * Visibilty Type: readonly StringCollection + */ + subtitleLanguages: null, + isHD: null, + is3D: null, + audioType: null, + isMultilingual: null, + + /* + * Decsription: + * + * Visibilty Type: readonly StringCollection + */ + audioLanguages: null, + + /* + * Decsription: + * + * Visibilty Type: readonly StringCollection + */ + genres: null, + recordingStartTime: null, + recordingDuration: null, + + /* + * Decsription: + * + * Visibilty Type: readonly BookmarkCollection + */ + bookmarks: null, + locked: null, + + /* + * FIXME: + * Yannis - 28/04/2015 - Initialize its own properties matching(not the inherited) + * programme field contained by its inherited property channel + */ + init: function(associatedScheduledRecording) { + this.isManual = true; + associatedScheduledRecording && + oipf.utils.initProperties.call(this, associatedScheduledRecording); + + this.id = createUUID(); + }, + + _setRecordingStartTime: function(recordingStartTime) { + this.recordingStartTime= recordingStartTime; + }, + + _setRecordingEndTime: function(recordingEndTime) { + this.recordingEndTime = recordingEndTime; + } + +}); + Added: oipf/js/impl/model/ScheduledRecording.js =================================================================== --- oipf/js/impl/model/ScheduledRecording.js (rev 0) +++ oipf/js/impl/model/ScheduledRecording.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,288 @@ +/* + * The ScheduledRecording object represents a scheduled programme in the system, + * i.e. a recording that is scheduled but which has not yet started. + * For group recordings (e.g. recording an entire series), + * a ScheduledRecording object is also used to represent a “parent” recording + * that enables management of the group recording without representing any of + * the actual recordings in the group. + * The values of the properties of a ScheduledRecording (except for + * startPadding and endPadding ) are provided when the object is created + * using one of the record() methods in section 7.10.1, for example by + * using a corresponding Programme object as argument for the record() method, + * and can not be changed for this scheduled recording object + * (except for startPadding and endPadding). + */ + +var ScheduledRecording = Class.extend({ + + /* + * This specification does not define values for these constants. + * Implementations may use any values as long as the value of + * each constant is unique. + */ + RECORDING_SCHEDULED: 0, + RECORDING_REC_STARTED: 1, + RECORDING_REC_COMPLETED: 2, + RECORDING_REC_PARTIALLY_COMPLETED: 3, + RECORDING_ERROR: 4, + ERROR_REC_RESOURCE_LIMITATION: 1712, + ERROR_INSUFFICIENT_STORAGE: 918, + ERROR_REC_UNKNOWN: 21, + + ID_TVA_GROUP_CRID: 2, + + /* + * Description: + * The state of the recording. Valid values are: + * RECORDING_REC_STARTED + * RECORDING_REC_COMPLETED + * RECORDING_REC_PARTIALLY_COMPLETED + * RECORDING_SCHEDULED + * RECORDING_ERROR + * + * Visibility Type: readonly Integer + */ + state: null, + + /* + * Description: + * If the state of the recording has changed due to an error, + * this field contains an error code detailing the type of error. + * This is only valid if the value of the state argument is RECORDING_ERROR + * or RECORDING_REC_PARTIALLY_COMPLETED otherwise + * this property SHALL be null . Valid values are: + * ERROR_REC_RESOURCE_LIMITATION + * ERROR_INSUFFICIENT_STORAGE + * ERROR_REC_UNKNOWN + * + * Visibility Type: readonly Integer + */ + error: null, + + scheduleID: null, + customID: null, + startPadding: null, + endPadding: null, + + /* + * Description: + * Bitfield indicating which days of the week the recording SHOULD + * be repeated. Values are as follows: + * ------------------------------------------------------------------------ + * Day | Bitfield Value + * ------------- ---------------------------------------------------------- + * Sunday | Indicates there are no analogue video outputs + * ------------- ---------------------------------------------------------- + * Monday | Indicates platform support for the NTSC TV standard. + * ------------- ---------------------------------------------------------- + * Tuesday | Indicates platform support for the PAL-BGH TV standard. + * ------------- ---------------------------------------------------------- + * Wednesday | Indicates platform support for the SECAM TV standard. + * ------------- ---------------------------------------------------------- + * Thursday | Indicates platform support for the PAL-M TV standard. + * ------------- ---------------------------------------------------------- + * Friday | Indicates platform support for the PAL-N TV standard. + * ------------------------------------------------------------------------ + * Saturday | Indicates platform support for the PAL-N TV standard. + * ------------------------------------------------------------------------ + * + * Visibility Type: readonly Integer + * + * FIXME: Yannis - 27/04/2015 - Express this properties as a bitfield. + */ + repeatDays: null, + + /* + * Description: + * The short name of the programme, e.g. 'Star Trek: DS9'. + * + * Type: String + */ + name: null, + + /* + * Description: + * The long name of the programme, e.g. 'Star Trek: Deep Space Nine'. + * If the long name is not available, this property will be undefined. + * + * Type: String + */ + longName: null, + + /* + * Description: + * The description of the programme, e.g. an episode synopsis. If no description is available, this property will be undefined. + * + * Type: String + */ + description: null, + + /* + * Description: + * The long description of the programme. If no description is available, this property will be undefined. + * + * Type: String + */ + longDescription: null, + + /* + * Description: + * The long description of the programme. If no description is available, this property will be undefined. + * + * Visibility Type: readonly Integer + */ + startTime: null, + + /* + * Description: + * The duration of the programme (in seconds). + * + * Visibility Type: readonly Integer + */ + duration: null, + + /* + * Description: + * Reference to the broadcast channel where the scheduled programme + * is available. + * + * Visibility Type: reaonly Channel + */ + channel: null, + + /* + * Description: + * true if the recording was scheduled using + * oipfRecordingScheduler.recordAt() or using a terminal-specific approach + * that does not use guide data to determine what to record, false otherwise. + * If false , then any fields whose name matches a field in the Programme + * object contains details from the programme guide on the programme + * that has been recorded. If true , only the channel , startTime and + * duration properties are required to be valid. + * + * Visibility Type: readonly Boolean + */ + isManual: null, + + /* + * Description: + * The episode number for the programme if it is part of a series. This property is undefined when the + * programme is not part of a series or the information is not available. + * + * Visibility Type: readonly Integer + */ + episode: null, + + /* + * Description: + * If the programme is part of a series, the total number of episodes in the series. This property is undefined + * when the programme is not part of a series or the information is not available. + * + * Visibility Type: readonly Integer + */ + totalEpisodes: null, + + /* + * Description: + * The unique identifier of the programme or series, e.g., + * a TV-Anytime CRID (Content Reference Identifier). + * + * Visibility Type: readonly Integer + */ + programmeID: null, + + /* + * Description: + * The type of identification used to reference the programme, + * as indicated by one of the ID_* constants + * defined above. + * + * Visibility Type: readonly Integer + */ + programmeIDType: null, + + /* + * Description: + * A collection of parental rating values for the programme for zero or more + * parental rating schemes supported by the OITF. The value of this property + * is typically provided by a corresponding “ Programme ” object that is + * used to schedule the recording and can not be changed for this scheduled + * recording object. If no parental rating information is available for this + * scheduled recording, this property is a ParentalRatingCollection + * object (as defined in section 7.9.5) with length 0. + * Note that if the parentalRating property contains a certain + * parental rating (e.g. PG-13) and the broadcastchannel associated with + * this scheduled recording has metadata that says that the content is + * rated PG-16,then the conflict resolution is implementation dependent. + * Note that this property was formerly called “parentalRating” + * (singular not plural). + * + * Visibility Type: readonly ParentalRatingCollection + */ + parentalRatings: null, + + /* + * Description: + * Application-specific information for this recording. + * This value is information that the DAE application can set in order + * to retain additional information on this scheduled recording. It is not + * changed by the OITF. The OITF SHALL support values up to and including + * 16 K Bytes in size. Strings longer than this MAY get truncated. + * + * Type: String + */ + customMetadata: null, + + init: function() { + var parameters = arguments; + + this.state = this.RECORDING_SCHEDULED; + this.scheduleID = createUUID(); + if (parameters.length == 1) { + this._initFromProgramme.apply(this, parameters); + } else { + this._initFromFields.apply(this, parameters); + } + }, + + _initFromProgramme: function(programme) { + console.log("Method _initFromProgramme called."); + var keys = Object.keys(programme); + + if (programme.programmeIDType == this.ID_TVA_GROUP_CRID) { + + } else { + for(var i = 0, l = keys.length; i < l; i++) { + this[keys[i]] = programme[keys[i]]; + } + this.isManual = false; + } + }, + + _initFromFields: function(startTime, duration, repeatDays, channelID) { + console.log("Method _initFromFields called"); + this.startTime = startTime; + this.duration = duration; + this.repeatDays = repeatDays; + this.isManual = true; + this.programmeID = undefined; + this.programmeIDType = undefined; + }, + + _setDuration: function(duration) { + this.duration = duration; + }, + + _setStartTime: function(startTime) { + this.startTime = startTime; + }, + + _setRepeatDays: function(repeatDays) { + this.repeatDays = repeatDays; + }, + + _setState: function(state) { + this.state = state; + } +}); + Added: oipf/js/impl/model/ScheduledRecordingCollection.js =================================================================== --- oipf/js/impl/model/ScheduledRecordingCollection.js (rev 0) +++ oipf/js/impl/model/ScheduledRecordingCollection.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,15 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var ScheduledRecordingCollection = Collection.extend({ + + init: function() { + this.super.init.apply(this, arguments); + } + +}); + + Modified: oipf/js/impl/model/SearchResults.js =================================================================== --- oipf/js/impl/model/SearchResults.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/SearchResults.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -86,7 +86,7 @@ * - offset: The number of items at the start of the result set to be skipped before data is retrieved. * * - count: The number of results to retrieve. - * FIX-ME: Yannis - 08/04/2015 - Verification about results ordering constraint + * FIXME: Yannis - 08/04/2015 - Verification about results ordering constraint */ getResults: function(offset, count) { var parameters = arguments; @@ -217,7 +217,7 @@ }, _getCurrentProgramme: function(programmes) { - var time = new Date().getTime(); + var time = new Date().getTime() / 1000; var constraints = this._search. _constraints.channels; @@ -229,7 +229,7 @@ programme.duration) { var stopTime = programme.startTime + - programme.duration*1000; + programme.duration; var self = this; if (time >= programme.startTime && time <= stopTime) { Modified: oipf/js/impl/model/SignalInfo.js =================================================================== --- oipf/js/impl/model/SignalInfo.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/SignalInfo.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -6,7 +6,7 @@ */ var SignalInfo = Class.extend({ - + /* * Description: * Signal strength measured in dBm, for example -31.5dBm. @@ -49,13 +49,8 @@ */ lock: null, - - init: function(strength, quality, quality, ber, snr, lock) { - this.strength = strength; - this.quality = quality; - this.ber = ber; - this.snr = snr; - this.lock = lock; + init: function(defaultProperties) { + oipf.utils.initProperties.call(this, defaultProperties); } }); Modified: oipf/js/impl/model/Tuner.js =================================================================== --- oipf/js/impl/model/Tuner.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/Tuner.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -88,8 +88,10 @@ */ powerOnExternal: null, - init: function(idTypes) { + init: function(name, idTypes, defaultProperties) { + oipf.utils.initProperties.call(this, defaultProperties); this.idTypes = idTypes; + this.name = name; } }); \ No newline at end of file Added: oipf/js/impl/model/constants/ConfigurationConstants.js =================================================================== --- oipf/js/impl/model/constants/ConfigurationConstants.js (rev 0) +++ oipf/js/impl/model/constants/ConfigurationConstants.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,15 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +var configurationConstants = { + pvrPolicy: {}, + tvStandard: {} +}; + +configurationConstants.pvrPolicy.NO_RECORDINGS = 0; +configurationConstants.pvrPolicy.WATCHED_RECORDINGS = 1; +configurationConstants.pvrPolicy.SPECIFIC_RECORDINGS = 2; + +configurationConstants.tvStandard.SECAM = 4; \ No newline at end of file Modified: oipf/js/impl/model/constants/DaeMimeType.js =================================================================== --- oipf/js/impl/model/constants/DaeMimeType.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/constants/DaeMimeType.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -3,23 +3,23 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -var CHANNEL_CONFIG_TYPE = "channelCongig"; //Not a DAE MIME Type -var VIDEO_BROADCAST_DAE_MIME_TYPE = "video/broadcast"; -var NOTIF_SOCKET_DAE_MIME_TYPE = "application/notifsocket"; var APPLICATION_MANAGER_DAE_MIME_TYPE = "application/oipfApplicationManager"; var CAPABILITIES_DAE_MIME_TYPE = "application/oipfCapabilities"; +var CHANNEL_CONFIG_TYPE = "channelConfig"; //Not a DAE MIME Type var COD_MANAGER_DAE_MIME_TYPE = "application/oipfCodManager"; +var COMMUNICATION_SERVICES_DAE_MIME_TYPE = "application/oipfCommunicationServices"; var CONFIGURATION_DAE_MIME_TYPE = "application/oipfConfiguration"; var DOWNLOAD_MANAGER_DAE_MIME_TYPE = "application/oipfDownloadManager"; var DOWNLOAD_TRIGGER_DAE_MIME_TYPE = "application/oipfDownloadTrigger"; var DRM_AGENT_DAE_MIME_TYPE = "application/oipfDrmAgent"; var GATEWAY_INFO_DAE_MIME_TYPE = "application/oipfGatewayInfo"; -var COMMUNICATION_SERVICES_DAE_MIME_TYPE = "application/oipfCommunicationServices"; var MDTF_DAE_MIME_TYPE = "application/oipfMDTF"; +var NOTIF_SOCKET_DAE_MIME_TYPE = "application/notifsocket"; var PARENTAL_CONTROL_MANAGER_DAE_MIME_TYPE = "application/oipfParentalControlManager"; var RECORDING_SCHEDULER_DAE_MIME_TYPE = "application/oipfRecordingScheduler"; var REMOTE_CONTROL_FUNCTION_DAE_MIME_TYPE = "application/oipfRemoteControlFunction"; var REMOTE_MANAGEMENT_DAE_MIME_TYPE = "application/oipfRemoteManagement"; var SEARCH_MANAGER_DAE_MIME_TYPE = "application/oipfSearchManager"; var STATUS_VIEW_DAE_MIME_TYPE = "application/oipfStatusView"; - +var VIDEO_BROADCAST_DAE_MIME_TYPE = "video/broadcast"; +var VIDEO_MPEG_DAE_MIME_TYPE = "video/mpeg"; Added: oipf/js/impl/model/constants/RecordingSchedulerConstants.js =================================================================== --- oipf/js/impl/model/constants/RecordingSchedulerConstants.js (rev 0) +++ oipf/js/impl/model/constants/RecordingSchedulerConstants.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,16 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var recordingConstants = { + state : {} +}; + +recordingConstants.state.STARTED = 1; +recordingConstants.state.COMPLETED = 2; +recordingConstants.state.SCHEDULED = 7; +recordingConstants.state.REMOVED = 8; +recordingConstants.state.BEFORE_STARTED = 9; +recordingConstants.state.UPDATED = 10; Modified: oipf/js/impl/model/constants/VideoBroadcastConstants.js =================================================================== --- oipf/js/impl/model/constants/VideoBroadcastConstants.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/impl/model/constants/VideoBroadcastConstants.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -1,8 +1,14 @@ -var videoBrodcastConstants = { - timeShiftMode : {} +var videoBroadcastConstants = { + timeShiftMode: {}, + state: {} }; -videoBrodcastConstants.timeShiftMode.OFF = 0; -videoBrodcastConstants.timeShiftMode.LOCAL = 1; -videoBrodcastConstants.timeShiftMode.NETWORK = 2; -videoBrodcastConstants.timeShiftMode.LOCAL_THEN_NETWORK = 3; \ No newline at end of file +videoBroadcastConstants.timeShiftMode.OFF = 0; +videoBroadcastConstants.timeShiftMode.LOCAL = 1; +videoBroadcastConstants.timeShiftMode.NETWORK = 2; +videoBroadcastConstants.timeShiftMode.LOCAL_THEN_NETWORK = 3; + +videoBroadcastConstants.state.UNREALIZED = 0; +videoBroadcastConstants.state.CONNECTING = 1; +videoBroadcastConstants.state.PRESENTING = 2; +videoBroadcastConstants.state.STOPPED = 3; \ No newline at end of file Modified: oipf/js/initObj/init.js =================================================================== --- oipf/js/initObj/init.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/initObj/init.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -52,9 +52,15 @@ "N/A" //reserved_future_use ]; -var metadata = data; - if (!oipfObjectFactory) { - var oipfObjectFactory = new OipfObjectFactory(); + var modelFactory = new ModelFactory(data); + var dateUtils = new DateUtils(); + var oipfObjectFactory = new OipfObjectFactory(modelFactory, dateUtils); } +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} + Added: oipf/js/test/CapabilitiesTest.js =================================================================== --- oipf/js/test/CapabilitiesTest.js (rev 0) +++ oipf/js/test/CapabilitiesTest.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,250 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +var CapabilitiesTest = TestCase.extend({ + init: function() { + this.super.init(); + }, + + beforeTest: function() { + this.capabilitiesObject = oipfObjectFactory.createCapabilitiesObject(); + }, + + afterTest: function() { + + }, + + /* + * FIXME: + * Yannis - 12/05/2015 - Instanciation of variable everyProperties. + */ + testOIFPNormConformityOfObject: function(resolve, reject) { + var everyProperties; + + for (var i = 0, l = everyProperties.length; i < l; i++) { + var currentProperty = everyProperties[i]; + if (!this.capabilitiesObject[currentProperty]) { + reject(); + return; + } + } + resolve(); + }, + + testHasCapabilityWithAnInvalidProfileName: function(resolve, reject) { + var profileName = "Toto"; + var result = this.capabilitiesObject.hasCapability(profileName); + + if (result) { + reject(); + } else { + resolve(); + } + }, + + testHasCapabilityForAtLeastOneBaseProfileName: function(resolve, reject) { + var baseProfileNameList = this.modelFactory + .getCapabilitiesProperties().baseUIProfileName; + var supportedProfileNumber = 0; + + for (var i = 0, l = baseProfileNameList.length; i < l; i++) { + var baseProfileName = baseProfileNameList[i]; + var result = this.capabilitiesObject.hasCapability(baseProfileName); + result && supportedProfileNumber++; + } + + if (supportedProfileNumber > 0) { + resolve(); + } else { + reject(); + } + }, + + testHasCapabilityForAllUIFragmentProfile: function(resolve, reject) { + var UIProfileNameFragmentList = this.modelFactory + .getCapabilitiesProperties().UIProfileNameFragment; + var supportedProfileNumber = 0; + + for (var i = 0, l = UIProfileNameFragmentList.length; i < l; i++) { + var UIProfileNameFragment = UIProfileNameFragmentList[i]; + var result = this.capabilitiesObject + .hasCapability(UIProfileNameFragment); + result && supportedProfileNumber++; + } + + if (supportedProfileNumber == UIProfileNameFragmentList.length) { + resolve(); + } else { + reject(); + } + }, + + getCapabilityAndNotifyResult: function(resolve, reject, profileName) { + var result = this.capabilitiesObject.hasCapability(profileName); + + if (result) { + resolve(); + } else { + reject(); + } + }, + + testHasCapabilityTRICKMODE: function(resolve, reject) { + var profileName = "+TRICKMODE"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityAVCAD: function(resolve, reject) { + var profileName = "+AVCAD"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDL: function(resolve, reject) { + var profileName = "+DL"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityIPTV_SDS: function(resolve, reject) { + var profileName = "+IPTV_SDS"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityIPTV_URI: function(resolve, reject) { + var profileName = "+IPTV_URI"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityANA: function(resolve, reject) { + var profileName = "+ANA"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDVB_C: function(resolve, reject) { + var profileName = "+DVB_C"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDVB_T: function(resolve, reject) { + var profileName = "+DVB_T"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDVB_S: function(resolve, reject) { + var profileName = "+DVB_S"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDVB_C2: function(resolve, reject) { + var profileName = "+DVB_C2"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDVB_T2: function(resolve, reject) { + var profileName = "+DVB_T2"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDVB_S2: function(resolve, reject) { + var profileName = "+DVB_S2"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityISDB_C: function(resolve, reject) { + var profileName = "+ISDB_C"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityISDB_T: function(resolve, reject) { + var profileName = "+ISDB_T"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityISDB_S: function(resolve, reject) { + var profileName = "+ISDB_S"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityMETA_BCG: function(resolve, reject) { + var profileName = "+META_BCG"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityMETA_EIT: function(resolve, reject) { + var profileName = "+META_EIT"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityMETA_SI: function(resolve, reject) { + var profileName = "+META_SI"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityITV_KEYS: function(resolve, reject) { + var profileName = "+ITV_KEYS"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityCONTROLLED: function(resolve, reject) { + var profileName = "+CONTROLLED"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityPVR: function(resolve, reject) { + var profileName = "+PVR"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityDRM: function(resolve, reject) { + var profileName = "+DRM"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityCommunicationServices: function(resolve, reject) { + var profileName = "+CommunicationServices"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilitySVG: function(resolve, reject) { + var profileName = "+SVG"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityPOINTER: function(resolve, reject) { + var profileName = "+POINTER"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityPOLLNOTIF: function(resolve, reject) { + var profileName = "+POLLNOTIF"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityHtml5Media: function(resolve, reject) { + var profileName = "+HTML5_MEDIA"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityWIDGETS: function(resolve, reject) { + var profileName = "+WIDGETS"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityRCF: function(resolve, reject) { + var profileName = "+RCF"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityTELEPHONY: function(resolve, reject) { + var profileName = "+TELEPHONY"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + }, + + testHasCapabilityVIDEOTELEPHONY: function(resolve, reject) { + var profileName = "+VIDEOTELEPHONY"; + this.getCapabilityAndNotifyResult(resolve, reject, profileName); + } + +}); + Added: oipf/js/test/ConfigurationTest.js =================================================================== --- oipf/js/test/ConfigurationTest.js (rev 0) +++ oipf/js/test/ConfigurationTest.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,315 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var ConfigurationTest = TestCase.extend({ + + init: function() { + this.super.init(); + }, + + beforeTest: function(resolve, reject) { + this.configurationObject = oipfObjectFactory.createConfigurationObject(); + this.localSystem = this.configurationObject.localSystem; + logTest("State: Pending"); + }, + + testSetScreenSize : function(resolve, reject){ + + if (this.localSystem) { + var result = this.localSystem.setScreenSize(1280, 720); + + if (result) { + resolve(); + } else { + throw new Error("Unexpected error"); + } + } else { + throw new Error("Unexpected error"); + } + }, + + testSetScreenSizeWithoutParameters: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError(this.localSystem.setScreenSize, resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetScreenSizeWithUnexpectedTypeParameters: function(resolve, reject) { + + if (this.localSystem) { + + this.waitForError( + this.localSystem.setScreenSize.bind(this.localSystem, "", ""), + resolve); + + } else { + throw new Error("Unexpected error"); + } + }, + + testSetScreenSizeWithExcessiveParametersNumber: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError( + this.localSystem.setScreenSize.bind(this.localSystem, 640, 480, 854), + resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetTvStandard: function(resolve, reject) { + + if (this.localSystem) { + var result = this.localSystem.setTVStandard(4); + if (result) { + resolve(); + } else { + throw new Error("Unexpected error"); + } + } else { + throw new Error("Unexpected error"); + } + }, + + testSetTvStandardWihtoutParameters: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError(this.localSystem.setTVStandard, resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetTvStandardWithUnexpectedTypeParameters: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError( + this.localSystem.setTVStandard.bind(this.localSystem, ""), + resolve); + + } else { + throw new Error("Unexpected error"); + } + }, + + testSetTvStandardWithExcessiveParametersNumber: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError( + this.localSystem.setTVStandard.bind(this.localSystem, 4, 4), + resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPvrSupport: function(resolve, reject) { + + if (this.localSystem) { + var result = this.localSystem.setPvrSupport(1); + if (result) { + resolve(); + } else { + throw new Error("Unexpected error"); + } + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPvrSupportWithoutParameters: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError(this.localSystem.setPvrSupport, resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPvrSupportWithUnexpectedTypeParameters: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError( + this.localSystem.setPvrSupport.bind(this.localSystem, {}), + resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPvrSupportWithExcessiveParametersNumber: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError( + this.localSystem.setPvrSupport.bind(this.localSystem, 0, 0, 0), + resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPowerState: function(resolve, reject) { + + if (this.localSystem) { + var result = this.localSystem.setPowerState(); + if (result) { + resolve(); + } else { + throw new Error("Unexpected error"); + } + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPowerStateWithoutParameters: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError(this.localSystem.setPowerState, resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPowerStateWithUnexpectedTypeParameters: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError( + this.localSystem.setPowerState.bind(this.localSystem, {}), + resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetPowerStateWithExcessiveParametersNumber: function(resolve, reject) { + + if (this.localSystem) { + this.waitForError( + this.localSystem.setPowerState.bind(this.localSystem, 0, 0, 0), + resolve); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetDigestCredentials: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.setDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetDigestCredentialsWithoutParameters: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.setDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetDigestCredentialsWithUnexpectedTypeParameters: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.setDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testSetDigestCredentialsWithExcessiveParametersNumber: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.setDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testClearDigestCredentials: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.clearDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testClearDigestCredentialsWithoutParameters: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.clearDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testClearDigestCredentialsWithUnexpectedTypeParameters: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.clearDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testClearDigestCredentialsWithExcessiveParametersNumber: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.clearDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testHasDigestCredentials: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.hasDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testHasDigestCredentialsWithoutParameters: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.hasDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testHasDigestCredentials: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.hasDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + testHasDigestCredentialsWithExcessiveParametersNumber: function(resolve, reject) { + + if (this.localSystem) { + this.localSystem.hasDigestCredentials(640, 480, 854); + } else { + throw new Error("Unexpected error"); + } + }, + + afterTest: function() { + } + +}); + Modified: oipf/js/test/RecordingSchedulerTest.js =================================================================== --- oipf/js/test/RecordingSchedulerTest.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/test/RecordingSchedulerTest.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -8,9 +8,13 @@ init: function() { this.super.init(); - this.timer = 3*60*1000; //2h, we had increased timer for unresolved tests. + this.timer = 3*60*1000; //3minutes, we had increased timer for unresolved tests. }, + createVideoBroadcast: function() { + this.vidBroadObj = oipfObjectFactory.createVideoBroadcastObject(); + }, + deleteAndStopStartedRecording: function() { var recordings = this.recordingSchedulerObject.recordings; @@ -38,7 +42,7 @@ this.recordingSchedulerObject .addEventListener("PVREvent", this.onPVREventCopy, false); - this.vidBroadObj = oipfObjectFactory.createVideoBroadcastObject(); + this.createVideoBroadcast(); this.onPlayStateChange = this.onChangeState.bind(this, resolve, reject); this.vidBroadObj .addEventListener("PlayStateChange", this.onPlayStateChange, false); Modified: oipf/js/test/SearchManagerTest.js =================================================================== --- oipf/js/test/SearchManagerTest.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/test/SearchManagerTest.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -5,10 +5,6 @@ */ var SearchManagerTest = TestCase.extend({ - SCHEDULED_CONTENT: 1, - - CONTENT_ON_DEMAND: 2, - UNREALIZED: 0, CONNECTING: 1, @@ -19,7 +15,8 @@ searchManagerObj: null, - init: function () { + init: function() { + this.super.init(); }, beforeTest: function(resolve, reject) { @@ -33,52 +30,7 @@ this.channel = null; logTest("State: Pending"); }, - - /* - * - * @param {type} resolve - * @param {type} reject - * @param {type} newState - * @param {type} errorCode - * @returns {undefined} - * FIX-ME: Yannis - 01/04/2015 - The verification done in else clause - * could be reviewed. - */ - onChangeState: function(resolve, reject, newState, errorCode) { - var currentTransition = this.transitions[this.currentIndex]; - var begin = currentTransition.begin; - var end = currentTransition.end; - var error = currentTransition.error; - console.log(this.vidBroadObj.playState); - if (begin == this.previousState && end == newState && error == errorCode) { - currentTransition.callback && currentTransition.callback(); - this.previousState = newState; - this.currentIndex++; - } else { - // - if (begin == this.CONNECTING - && this.transitions.length == this.currentIndex + 1) { - reject("Untestable case for the moment."); - } else { - reject("Invalid state"); - } - - } - }, - - addTransition: function(begin, end, callback) { - this.addTransitionWithError(begin, end, null, callback); - }, - - addTransitionWithError: function(begin, end, error, callback) { - this.transitions.push({ - begin: begin, - end: end, - error: error, - callback: callback - }); - }, - + afterTest: function(resolve, reject) { this.vidBroadObj.removeEventListener("PlayStateChange", this.onPlayStateChange); @@ -87,6 +39,42 @@ this.timerManager.clearTimer(); }, + testFindAFinishedProgramme: function(resolve, reject) { + var self = this; + var metadataSearch = self.searchManagerObj. + createSearch(self.SCHEDULED_CONTENT); + var now = Math.round(Date.now() / 1000); + var query = metadataSearch.createQuery("Programme.startTime", 4, now); + metadataSearch.setQuery(query); + + var offset = 0; + var count = 4; + metadataSearch.result.getResults(offset, count); + + this.searchManagerObj.onMetadataSearch = function(search, state) { + + console.log("[INFO]: onMetadataSearch called"); + + switch (state) { + + case 0: + if (!self.assertEquals(search.result.length, 0)) { + console.log("[TEST-RUNNING][Info] Label: Obtain current program according to oipf norm, State: found"); + resolve(); + } else { + console.log("[TEST-RUNNING][Info] Label: Obtain current program according to oipf norm, State: not found"); + reject(); + } + break; + + default: + console.log("Unknow state"); + reject(); + } + }; + + }, + testGetCurrentProgrammeFromStream: function (resolve, reject) { var self = this; @@ -147,27 +135,19 @@ testSearchingForASpecificProgrammeByName: function(resolve, reject) { var self = this; - var value = "X:ENIUS"; - -// this.addTransition(this.UNREALIZED, this.CONNECTING); - -// this.addTransition(this.CONNECTING, this.PRESENTING, function() { + var value = "X:enius"; - var stat = "Pending"; - logTest("State: " + stat); - var metadataSearch = self.searchManagerObj. - createSearch(self.SCHEDULED_CONTENT); - - var query = metadataSearch.createQuery("Programme.name", 0, - value); - metadataSearch.setQuery(query); - - var offset = 0; - var count = 1; - metadataSearch.result.getResults(offset, count); -// //Must return undefined else wrong implementation of getResults method -// console.log(metaDataSearch.result[0]); -// }); + var stat = "Pending"; + logTest("State: " + stat); + var metadataSearch = self.searchManagerObj. + createSearch(self.SCHEDULED_CONTENT); + + var query = metadataSearch.createQuery("Programme.name", 0, value); + metadataSearch.setQuery(query); + + var offset = 0; + var count = 1; + metadataSearch.result.getResults(offset, count); this.searchManagerObj.onMetadataSearch = function(search, state) { Modified: oipf/js/test/Test.js =================================================================== --- oipf/js/test/Test.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/test/Test.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -337,6 +337,10 @@ method: "testCreateSearchWithZero" }, { + label: "Looking for a programme already broadcasted.", + method: "testFindAFinishedProgramme" + }, + { label: "Obtain current program according to oipf norm.", method: "testGetCurrentProgrammeFromStream" }, @@ -528,12 +532,207 @@ ]},{ name: "RecordingSchedulerTest", object: new RecordingSchedulerTest(), - timer: 120000, tests: [ { label: "Call method 'setRecord' in order to record current programme.", method: "testRecordCurrentProgramme" + }, + { + label: "Try to call method 'setRecord' with a finished programme.", + method: "testRecordAFinishedProgramme" + }, + { + label: "Call method 'setRecordAt' in order to record current programme.", + method: "testRecordAtCurrentProgramme" + }, + { + label: "Call method 'stop' after a scheduling recording.", + method: "testStopAScheduledRecording" + }, + { + label: "Call method 'stop' while a recording.", + method: "testStopAnOngoingRecording" + }, + { + label: "Call method 'stop' at the end of a recording.", + method: "testStopACompletedRecording" + }, + { + label: "Call method 'remove' after a scheduling recording.", + method: "testRemoveAScheduledRecording" + }, + { + label: "Call method 'remove' while a recording.", + method: "testRemoveAnOngoingRecording" + }, + { + label: "Call method 'remove' at the end of a recording.", + method: "testRemoveACompletedRecording" + }, + { + label: "Call method 'update' to update start time of a scheduled recording", + method: "testUpdateAScheduledRecordingOnStartTime" + }, + { + label: "Call method 'update' to update duration of a scheduled recording.", + method: "testUpdateAScheduledRecordingOnDuration" + }, + { + label: "Call method 'update' to update duration of an in-progress recording.", + method: "testUpdateAnOngoingRecordingWithAValidDuration" + }, + { + label: "Call method 'update' to update duration of an in-progress recording with a short duration.", + method: "testUpdateAnOngoingRecordingWithATooShortDuration" + }, + { + label: "Call method 'update' to update start time of an in-progress recording.", + method: "testUpdateAnOngoingRecordingOnStartTime" + }, + { + label: "Call method 'update' to update repetition frequency of an in-progress recording.", + method: "testUpdateAnOngoingRecordingOnRepeatDays" } + ]},{ + name: "CapabilitiesTest", + object: new CapabilitiesTest(), + tests: [ + { + label: "Call method 'hasCapability' with an invalid profile name.", + method: "testHasCapabilityWithAnInvalidProfileName" + }, + { + label: "Call method 'hasCapability' to verify that the TV support at least one of pre-defined base UI profiles.", + method: "testHasCapabilityForAtLeastOneBaseProfileName" + }, + { + label: "Call method 'hasCapability' to verify if the TV support all pre-defined UI fragments profiles.", + method: "testHasCapabilityForAllUIFragmentProfile" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'TRICKMODE'.", + method: "testHasCapabilityTRICKMODE" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'AVCAD'.", + method: "testHasCapabilityAVCAD" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'DL'.", + method: "testHasCapabilityDL" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'IPTV_SDS'.", + method: "testHasCapabilityIPTV_SDS" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'IPTV_URI'.", + method: "testHasCapabilityIPTV_URI" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'ANA'.", + method: "testHasCapabilityANA" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'DVB_C'.", + method: "testHasCapabilityDVB_C" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'DVB_T'.", + method: "testHasCapabilityDVB_T" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'DVB_S'.", + method: "testHasCapabilityDVB_S" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'DVB_C2'.", + method: "testHasCapabilityDVB_C2" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'DVB_T2'.", + method: "testHasCapabilityDVB_T2" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'DVB_S2'.", + method: "testHasCapabilityDVB_S2" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'ISDB_C'.", + method: "testHasCapabilityISDB_C" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'ISDB_T'.", + method: "testHasCapabilityISDB_T" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'ISDB_S'.", + method: "testHasCapabilityISDB_S" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'META_BCG'.", + method: "testHasCapabilityMETA_BCG" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'META_EIT'.", + method: "testHasCapabilityMETA_EIT" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'META_SI'.", + method: "testHasCapabilityMETA_SI" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'ITV_KEYS'.", + method: "testHasCapabilityITV_KEYS" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature 'CONTROLLED'.", + method: "testHasCapabilityCONTROLLED" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'PVR').", + method: "testHasCapabilityPVR" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'DRM').", + method: "testHasCapabilityDRM" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'CommunicationServices').", + method: "testHasCapabilityCommunicationServices" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'SVG').", + method: "testHasCapabilitySVG" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'POINTER').", + method: "testHasCapabilityPOINTER" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'POLLNOTIF').", + method: "testHasCapabilityPOLLNOTIF" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'HTML5_MEDIA').", + method: "testHasCapabilityHtml5Media" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'WIDGETS').", + method: "testHasCapabilityWIDGETS" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'RCF').", + method: "testHasCapabilityRCF" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'TELEPHONY').", + method: "testHasCapabilityTELEPHONY" + }, + { + label: "Call method 'hasCapability' to verify if the TV support the feature recording(UI profile name fragment: 'VIDEOTELEPHONY').", + method: "testHasCapabilityVIDEOTELEPHONY" + } ] }], @@ -543,6 +742,8 @@ start: true, intervalID: 0 }; + + this.sectionsID = []; }, runAll: function() { @@ -611,6 +812,7 @@ this.percentageCalculating(this.testsObjects[i].results); this.resultsPercentageFailed += this.testsObjects[i].results.failed; this.resultsPercentageSucceeded += this.testsObjects[i].results.succeeded; + this.results.push(this.testsObjects[i].results); } this.resultsPercentageFailed = this.resultsPercentageFailed/this.testsObjects.length; this.resultsPercentageSucceeded = this.resultsPercentageSucceeded/this.testsObjects.length; @@ -621,6 +823,8 @@ var id = "globalTestResultsTable"; var tableResult = document.getElementById(id); var content; + content += "<table>"; + content += "<tbody>"; content += "<thead>"; content += "<tr>"; content += "<th></th>"; @@ -628,18 +832,13 @@ content += "<th>Failed (%)</th>"; content += "</tr>"; content += "</thead>"; - content += "<tbody>"; -// for (var i = 0, l = this.results.length; i < l; i++) { -// content += -// this.percentageCalculating(this.results[i]); -// this.result.percentageFailed += this.results[i].failed; -// this.result.percentageSucceeded += this.results[i].succeeded -// content += "<tr>"; -// content += "<th>" + this.results[i].testName + "<th>"; -// content += "<td>" + + "</td>"; -// content += "<td>" + + "</td>"; -// content += "</tr>"; -// } + for (var i = 0, l = this.results.length; i < l; i++) { + content += "<tr>"; + content += "<th>" + this.results[i].testName + "</th>"; + content += "<td>" + this.results[i].succeeded + "</td>"; + content += "<td>" + this.results[i].failed + "</td>"; + content += "</tr>"; + } content += "<tr>"; content += "<th>Total</th>"; content += "<td>" + this.resultsPercentageSucceeded + "</td>"; @@ -684,7 +883,7 @@ content += "<div id='testControllerDiv'>"; content += "<div id='titleTestControllerDiv'><h4>Test Controller<h4></div>"; content += "<button id='runAllBtn'>Run All</button>"; - content += "<button id='stopAllBtn'>Stop All</button>"; + content += "<button id='displayConfigBtn'>Hide/Show</button>"; content += "<div id='globalTestResultsDiv'>"; content += "<div id='titleGlobalTestResultsDiv'><h4>Global Test Results<h4></div>"; content += "<table id='globalTestResultsTable'></table>"; @@ -701,7 +900,10 @@ + "<button id='" + currentObject.name + "HideShowBtn'>Hide/Show</button>" + "<button id='runAll" + currentObject.name + "Btn'>Run tests of this section</button>"; content += "</div>"; - content += "<div id='" + currentObject.name + "Section'>"; + var idOfTestSection = currentObject.name + "Section"; + this.sectionsID.push(idOfTestSection); + + content += "<div id=" + idOfTestSection + ">"; content += "<table id='" + currentObject.name + "Table'>"; content += "<tbody>"; content += "<thead>"; @@ -733,7 +935,7 @@ } content += "</div>"; content += "</div>"; - document.body.innerHTML = content; + document.body.innerHTML += content; }, updateTestResult: function(currentTest, object) { @@ -790,7 +992,7 @@ updateTestResultError: function(timeStart, timeEnd, currentTest, message) { document.getElementById(currentTest["method"] + "Result").textContent = message || "Error"; - document.getElementById(currentTest["method"] + "Result").style.backgroundColor = "red"; + document.getElementById(currentTest["method"] + "Result").style.backgroundColor = this.colorManaging(message); document.getElementById(currentTest["method"] + "Duration").textContent = (timeEnd - timeStart).toFixed(2) + " ms"; }, @@ -821,6 +1023,26 @@ stopAnimationInProgress: function(object, currentTest) { clearInterval(this.animation.intervalID); + this.animation.id = 1; + this.animation.start = true; + this.animation.intervalID = null; + + }, + + colorManaging: function(errorMessage) { + var map = { + "No result returned.": "orange", + "Untestable case for the moment.": "sandybrown", + "Invalid state.": "orangered" + }; + + if (!errorMessage) { + return "red"; + } else if (typeof errorMessage == "string") { + return map[errorMessage]; + } else if (errorMessage instanceof Error) { + return "tomato"; + } } }); Modified: oipf/js/test/TestCase.js =================================================================== --- oipf/js/test/TestCase.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/test/TestCase.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -6,8 +6,22 @@ var TestCase = Class.extend({ init: function() { + this.modelFactory = new ModelFactory(); + this.UNREALIZED = videoBroadcastConstants.state.UNREALIZED; + this.CONNECTING = videoBroadcastConstants.state.CONNECTING; + this.PRESENTING = videoBroadcastConstants.state.PRESENTING; + this.SCHEDULED = recordingConstants.state.SCHEDULED; + this.STARTED = recordingConstants.state.STARTED; + this.COMPLETED = recordingConstants.state.COMPLETED; + this.BEFORE_STARTED = recordingConstants.state.BEFORE_STARTED; + this.REMOVED = recordingConstants.state.REMOVED; + this.UPDATED = recordingConstants.state.UPDATED; + this.SCHEDULED_CONTENT = 1; + this.CONTENT_ON_DEMAND = 2; + this.dateUtils = new DateUtils(); this.timerManager = new TimerManager(); this.timeout = this.timerManager.createTimer.bind(this.timerManager); +// this.transitions = null; }, assertNotUndefined : function(elmt) { @@ -30,6 +44,50 @@ console.log(val); resolve(); }); + }, + + addTransition: function(begin, end, callback) { + this.addTransitionWithError(begin, end, null, callback); + }, + + addTransitionWithError: function(begin, end, error, callback) { + this.transitions.push({ + begin: begin, + end: end, + error: error, + callback: callback + }); + }, + + /* + * + * @param {type} resolve + * @param {type} reject + * @param {type} newState + * @param {type} errorCode + * @returns {undefined} + * FIXME: Yannis - 01/04/2015 - The verification done in else clause + * could be reviewed. + */ + onChangeState: function(resolve, reject, newState, errorCode) { + var currentTransition = this.transitions[this.currentIndex]; + var begin = currentTransition.begin; + var end = currentTransition.end; + var error = currentTransition.error; + console.log(this.vidBroadObj.playState); + if (begin == this.previousState && end == newState && error == errorCode) { + currentTransition.callback && currentTransition.callback(); + this.previousState = newState; + this.currentIndex++; + } else { + // + if (begin == this.CONNECTING + && this.transitions.length == this.currentIndex + 1) { + reject("Untestable case for the moment."); + } else { + reject("Invalid state."); + } + } } }); Modified: oipf/js/test/VideoBroadcastTest.js =================================================================== --- oipf/js/test/VideoBroadcastTest.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/test/VideoBroadcastTest.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -36,7 +36,7 @@ }, init: function() { - + this.super.init(); }, beforeTest: function(resolve, reject) { @@ -62,51 +62,38 @@ } return null; }, - /* - * - * @param {type} resolve - * @param {type} reject - * @param {type} newState - * @param {type} errorCode - * @returns {undefined} - * FIX-ME: Yannis - 01/04/2015 - The verification done in else clause - * could be reviewed. - */ - onChangeState: function(resolve, reject, newState, errorCode) { - var currentTransition = this.transitions[this.currentIndex]; - var begin = currentTransition.begin; - var end = currentTransition.end; - var error = currentTransition.error; - console.log(this.vidBroadObj.playState); - if (begin == this.previousState && end == newState && error == errorCode) { - currentTransition.callback && currentTransition.callback(); - this.previousState = newState; - this.currentIndex++; - } else { - // - if (begin == this.CONNECTING - && this.transitions.length == this.currentIndex + 1) { - reject("Untestable case for the moment."); - } else { - reject("Invalid state"); - } - - } - }, - addTransition: function(begin, end, callback) { - this.addTransitionWithError(begin, end, null, callback); - }, +// /* +// * +// * @param {type} resolve +// * @param {type} reject +// * @param {type} newState +// * @param {type} errorCode +// * @returns {undefined} +// * FIXME: Yannis - 01/04/2015 - The verification done in else clause +// * could be reviewed. +// */ +// onChangeState: function(resolve, reject, newState, errorCode) { +// var currentTransition = this.transitions[this.currentIndex]; +// var begin = currentTransition.begin; +// var end = currentTransition.end; +// var error = currentTransition.error; +// console.log(this.vidBroadObj.playState); +// if (begin == this.previousState && end == newState && error == errorCode) { +// currentTransition.callback && currentTransition.callback(); +// this.previousState = newState; +// this.currentIndex++; +// } else { +// // +// if (begin == this.CONNECTING +// && this.transitions.length == this.currentIndex + 1) { +// reject("Untestable case for the moment."); +// } else { +// reject("Invalid state"); +// } +// } +// }, - addTransitionWithError: function(begin, end, error, callback) { - this.transitions.push({ - begin: begin, - end: end, - error: error, - callback: callback - }); - }, - /* * This method must throw a error by using the method reject. * @@ -136,7 +123,6 @@ // }, testDoubleBindToCurrentChannel: function(resolve, reject) { - var self = this; this.addTransition(this.UNREALIZED, this.CONNECTING); @@ -227,8 +213,7 @@ reject(); }; this.vidBroadObj.prevChannel(); - this.timeout(3000) - .then(resolve); + this.timeout(3000).then(resolve); }, @@ -246,7 +231,7 @@ if (self.assertNotNull(channel) && self.assertEquals(this.vidBroadObj, this.PRESENTING)) { logTest("State: Successful"); - resolve("Successfull"); + resolve(); } else { logTest("State: Failure"); reject("Failure : The channel is null for a unknown reason or wrong play state."); Added: oipf/js/test/newjavascript.js =================================================================== --- oipf/js/test/newjavascript.js (rev 0) +++ oipf/js/test/newjavascript.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,58 @@ +/* + * To change license header, choose License Headers in Project Properties. + * To change template file, choose Tools | Templates + * and open the template in the editor. + */ +var SCHEDULED = 7; +var STARTED = 1; +var BEFORE_STARTED = 9; +var COMPLETED = 2; +var transitions = []; +var currentIndex; +var vidBroadObj = oipfObjectFactory.createVideoBroadcastObject(); +var recordingSchedulerObject = + oipfObjectFactory.createRecordingSchedulerObject(); +var previousState; + +function addTransitionWithError(begin, end, error, callback) { + transitions.push({ + begin: begin, + end: end, + error: error, + callback: callback + }); +}; + +function addTransition(begin, end, callback) { + addTransitionWithError(begin, end, null, callback); +}; + +recordingSchedulerObject.onPVREvent = function(newState, recordings) { + if (currentIndex < transitions.length) { + console.log("PVREvent received: State:", newState); + var currentTransition = transitions[currentIndex]; + var begin = currentTransition.begin; + var end = currentTransition.end; + + if (begin == previousState && end == newState) { + currentTransition.callback && currentTransition.callback(); + previousState = newState; + currentIndex++; + } else { + reject("Invalid state."); + } + } else { + console.log("Any others transitions have been set."); + } +}; + +addTransition(null, SCHEDULED); +addTransition(SCHEDULED, BEFORE_STARTED); +addTransition(BEFORE_STARTED, STARTED); +addTransition(STARTED, COMPLETED); +var channel = vidBroadObj.currentChannel; +var currentTime = Math.round(Date.now()/1000); +recording = recordingSchedulerObject.recordAt(currentTime, + 1*60, 0x00, channel.ccid); +console.log(recording); + Added: oipf/js/utils/DateUtils.js =================================================================== --- oipf/js/utils/DateUtils.js (rev 0) +++ oipf/js/utils/DateUtils.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var DateUtils = Class.extend({ + + init: function() { + this.date = new Date(); + this._yesterday = new Date(this.date.getFullYear(), + this.date.getUTCMonth(), + this.date.getUTCDate()-1); + }, + + millisecondsToSeconds: function(timeInMilliseconds) { + return timeInMilliseconds / 1000; + }, + + nowInSeconds: function() { + return this.millisecondsToSeconds(Date.now()); + }, + + secondsToMilliseconds: function(timeInSeconds) { + return timeInSeconds * 1000; + }, + + secondsToMinutes: function(timeInSeconds) { + return timeInSeconds / 60; + }, + + yesterday: function() { + return this._yesterday; + } + +}); Modified: oipf/js/utils/EventManager.js =================================================================== --- oipf/js/utils/EventManager.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/utils/EventManager.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -20,6 +20,7 @@ var listeners = target._listeners[event.type]; listeners && listeners.forEach(function(listener){ + console.log(">>fireEvent") oipf.utils.timeout(0) .then(listener.apply.bind(listener, target, event.detail)); }); @@ -28,7 +29,7 @@ callback && callback.apply(target, event.detail); }, - + removeEventListener: function(type, listener, target){ var listeners = target._listeners[type]; Added: oipf/js/utils/MetaData.js =================================================================== --- oipf/js/utils/MetaData.js (rev 0) +++ oipf/js/utils/MetaData.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,9 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var MetaData = Class.extend({ + +}); Added: oipf/js/utils/OrderingUtils.js =================================================================== --- oipf/js/utils/OrderingUtils.js (rev 0) +++ oipf/js/utils/OrderingUtils.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,15 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var orderingUtils = {}; + +orderingUtils.ascendingBy = function(field) { + +}; + +orderingUtils.ascending = function() { + +}; Added: oipf/js/utils/TimerRecordingManager.js =================================================================== --- oipf/js/utils/TimerRecordingManager.js (rev 0) +++ oipf/js/utils/TimerRecordingManager.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -0,0 +1,29 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +var TimerRecordingManager = Class.extend({ + + init: function() { + this.recordingTimers = {}; + }, + + createTimer: function(time) { + var timer = new Timeout(time); + console.log("createTimer", timer.timerId); + return timer; + }, + + clearTimer: function(recordingID) { + console.log("Method clearTimer called."); + var timers = this.recordingTimers[recordingID]; + timers.start && timers.start.cancel() && + console.log("cancelTimer", "Start timer: ", timers.start.timerId); + timers.end && timers.end.cancel() && + console.log("cancelTimer", "End timer: ", timers.end.timerId); + } + +}); + Modified: oipf/js/utils/Utils.js =================================================================== --- oipf/js/utils/Utils.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/utils/Utils.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -6,6 +6,14 @@ utils: {} }; + +oipf.utils.initProperties = function(defaultProperties) { + var keys = Object.keys(defaultProperties); + for (var i = 0, l = keys.length; i < l; i++) { + this[keys[i]] = defaultProperties[keys[i]]; + } +}; + oipf.utils.timeout = function(time) { return new Timeout(time); }; @@ -43,10 +51,14 @@ return Math.floor(Math.random() * 9000) + 1000; }; +oipf.utils.getRandomNumberBetweenMinMax = function(min, max) { + return Math.floor(Math.random() * (max - min)) + min; +}; + oipf.utils.isPresent = function(list, element) { for (var i = 0, l = list.length; i < l; i++) { - if (oipf.utils.equals(list[i], element)) { + if (oipf.utils.equals(list[i].name, element)) { return true; } } Modified: oipf/js/utils/XmlParser.js =================================================================== --- oipf/js/utils/XmlParser.js 2015-05-13 15:32:07 UTC (rev 1339) +++ oipf/js/utils/XmlParser.js 2015-05-13 15:36:40 UTC (rev 1340) @@ -20,7 +20,7 @@ createAXmlStringDocument: function(defaultPropertiesObject) { console.log("Method createAXmlStringDocument called"); - var defaultProperties = defaultPropertiesObject.default; + var defaultProperties = defaultPropertiesObject.rearrangeDefaultProperties(); var objectsNames = Object.keys(defaultProperties); var xmlStringDocument = "<" + defaultPropertiesObject.roots + ">"; for (var i = 0, l = objectsNames.length; i < l; i++) {