Repository: ina-foss/amalia.js Branch: master Commit: 93563895569f Files: 154 Total size: 1.4 MB Directory structure: gitextract_wtstfblr/ ├── .gitignore ├── .jshintrc ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── package.json ├── releases.md ├── samples/ │ ├── ajs-player.html │ ├── ajs-plugin-captions.html │ ├── ajs-plugin-editor.html │ ├── ajs-plugin-overlay.html │ ├── ajs-plugin-text-sync.html │ ├── ajs-plugin-timeline.html │ ├── ajs-plugin-watermark.html │ ├── ajs-webfont.html │ └── css/ │ ├── amalia-js-demo.css │ └── default.css ├── samples-data/ │ └── examples/ │ └── json/ │ ├── amalia-simple01.json │ ├── amalia01-ball.json │ ├── amalia01-events.json │ ├── amalia01-kf.json │ ├── amalia01-overlay.json │ └── amalia01-text.json ├── src/ │ ├── .jshintrc │ ├── LICENSE │ ├── THIRD_PARTY_LICENSES │ ├── assets/ │ │ ├── fonts/ │ │ │ └── ajs-webfont.afm │ │ ├── less/ │ │ │ ├── ajs-animations.less │ │ │ ├── ajs-webfont.less │ │ │ ├── default-style.less │ │ │ ├── default.less │ │ │ ├── player-custom-control-bar.less │ │ │ ├── player.less │ │ │ ├── plugin-captions.less │ │ │ ├── plugin-editor.less │ │ │ ├── plugin-menu-contextuel.less │ │ │ ├── plugin-overlay.less │ │ │ ├── plugin-selected-item-editor.less │ │ │ ├── plugin-storyboard.less │ │ │ ├── plugin-text-sync.less │ │ │ ├── plugin-timeline.less │ │ │ ├── plugin-watermark.less │ │ │ └── plugin.less │ │ └── sass/ │ │ ├── _ajs-animations.scss │ │ ├── _ajs-mixins.scss │ │ ├── _ajs-webfont.scss │ │ ├── _default-style.scss │ │ ├── _player-custom-control-bar.scss │ │ ├── _player.scss │ │ ├── _plugin-captions.scss │ │ ├── _plugin-editor.scss │ │ ├── _plugin-menu-contextuel.scss │ │ ├── _plugin-overlay.scss │ │ ├── _plugin-selected-item-editor.scss │ │ ├── _plugin-storyboard.scss │ │ ├── _plugin-text-sync.scss │ │ ├── _plugin-timeline.scss │ │ ├── _plugin-watermark.scss │ │ ├── _plugin.scss │ │ ├── _plugin_d3js_chart.scss │ │ └── main.scss │ ├── helpers/ │ │ ├── browser-feature-detection.js │ │ ├── html5-helper.js │ │ └── utilities-helper.js │ ├── i18n/ │ │ ├── player-error-message-en.js │ │ └── player-message-en.js │ ├── ina-player.js │ ├── log/ │ │ ├── .jshintrc │ │ └── log-handler.js │ ├── player/ │ │ ├── base-player.js │ │ ├── constants/ │ │ │ ├── player-error-code.js │ │ │ ├── player-event-type.js │ │ │ └── player-message.js │ │ ├── loader/ │ │ │ ├── base-loader.js │ │ │ ├── http-loader.js │ │ │ └── ws-loader.js │ │ ├── loaderBase.js │ │ ├── local-storage-manager.js │ │ ├── media-factory.js │ │ ├── media-type-dash-mpeg.js │ │ ├── media-type-manager.js │ │ ├── metadata/ │ │ │ ├── localisation-manager.js │ │ │ └── metadata-manager.js │ │ ├── parsers/ │ │ │ └── base-parser-metadata.js │ │ ├── player-html5.js │ │ ├── plugins/ │ │ │ ├── captions-base.js │ │ │ ├── context-menu-plugin.js │ │ │ ├── custom-control-bar.js │ │ │ ├── plugin-base-multi-blocks.js │ │ │ ├── plugin-base-simple-block.js │ │ │ ├── plugin-base.js │ │ │ ├── plugin-binding-manager.js │ │ │ └── plugin-manager.js │ │ ├── shortcuts-manager.js │ │ └── widgets/ │ │ ├── base-button.js │ │ ├── cast-button.js │ │ ├── channel-volume-control-bar.js │ │ ├── fullscreen-button.js │ │ ├── jog-shuttle-button.js │ │ ├── label.js │ │ ├── pause-button.js │ │ ├── play-button.js │ │ ├── progress-bar.js │ │ ├── time-label.js │ │ ├── volume-control-bar.js │ │ └── widget-base.js │ ├── player-map.js │ ├── plugins/ │ │ ├── captions/ │ │ │ └── captions.js │ │ ├── control-bar/ │ │ │ └── progress-bar.js │ │ ├── d3js-chart/ │ │ │ └── plugin-d3js-chart.js │ │ ├── editor/ │ │ │ ├── plugin-metadata-block-editor.js │ │ │ ├── plugin-metadata-item-editor.js │ │ │ ├── plugin-metadata-items-editor.js │ │ │ ├── plugin-metadata-items-ref-editor.js │ │ │ └── plugin-metadata-list-editor.js │ │ ├── overlay/ │ │ │ ├── draw-base.js │ │ │ ├── draw-ellipse.js │ │ │ ├── draw-rect.js │ │ │ ├── overlay.js │ │ │ └── spatials-data-parser.js │ │ ├── storyboard/ │ │ │ ├── base-frame-position-calculator.js │ │ │ └── plugin-storyboard.js │ │ ├── text-sync/ │ │ │ ├── component.js │ │ │ └── text-sync.js │ │ ├── timeline/ │ │ │ ├── base-component.js │ │ │ ├── cuepoints-component.js │ │ │ ├── default-configuration.js │ │ │ ├── focus-component.js │ │ │ ├── histogram-component.js │ │ │ ├── images-component.js │ │ │ ├── segments-component.js │ │ │ ├── tic-component.js │ │ │ ├── time-axis-component.js │ │ │ ├── timeline.js │ │ │ ├── visual-component.js │ │ │ └── zoom-component.js │ │ ├── watermark/ │ │ │ └── watermark.js │ │ └── yt-player/ │ │ └── yt-player.js │ └── utils/ │ ├── jquery-class.js │ ├── jquery-debouncedresize.js │ ├── jquery-knob.js │ ├── jquery.hotkeys.js │ ├── jquery.ui.touch-punch.js │ └── raphael_free_transform.js └── tests/ ├── .jshintrc ├── log/ │ ├── logHandler_test.html │ └── logHandler_test.js └── player/ ├── LoaderBase_test.html ├── LoaderBase_test.js ├── PlayerErrorCode_test.html ├── PlayerErrorCode_test.js └── data/ ├── VideoEntities.json └── VideoKeyframes.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .svn .bowerrc build build-doc .idea bower_components node_modules npm-debug.log package-lock.json ================================================ FILE: .jshintrc ================================================ { "curly": true, "eqeqeq": true, "immed": true, "latedef": true, "newcap": true, "noarg": true, "sub": true, "undef": true, "unused": true, "boss": true, "eqnull": true, "node": true } ================================================ FILE: Gruntfile.js ================================================ 'use strict'; module.exports = function (grunt) { require('load-grunt-tasks')(grunt); require('time-grunt')(grunt); grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), jshint: { gruntfile: { options: { jshintrc: '.jshintrc' }, src: 'Gruntfile.js' }, player: { options: { jshintrc: 'src/.jshintrc' }, src: [ 'src/player/**/*.js', 'src/helpers/**/*.js', 'src/plugins/**/*.js', 'src/*.js' ] }, i18n: { options: { jshintrc: 'src/.jshintrc' }, src: [ 'src/i18n/**/*.js' ] }, // Configuration with console.log log: { options: { jshintrc: 'src/log/.jshintrc' }, src: [ 'src/log/**/*.js' ] }, // Configuration with ok,notEqual,deepEqual,notDeepEqual... tests: { options: { jshintrc: 'tests/.jshintrc' }, src: [ 'tests/**/*.js' ] } }, uglify: { options: { banner: '/*!<%= pkg.description %> V<%= pkg.version %>, © <%= pkg.author %> <%= grunt.template.today("yyyy") %> */\n<%= pkg.licenseText %>', compress: { global_defs: { "_PlayerAmaliaVersion_": '<%= pkg.description %> V<%= pkg.version %>, © <%= pkg.author %> <%= grunt.template.today("yyyy") %>', "_PlayerAmaliaHomepage_": '<%= pkg.homepage %>' } } }, build: { files: { 'build/js/i18n/<%= pkg.name %>-message-en.js': [ 'src/i18n/player-error-message-en.js', 'src/i18n/player-message-en.js' ], 'build/js/<%= pkg.name %>-logger.min.js': [ 'src/log/log-handler.js' ], 'build/js/<%= pkg.name %>.min.js': [ 'src/utils/jquery-class.js', 'src/utils/jquery-knob.js', 'src/utils/jquery.ui.touch-punch.js', 'src/utils/dash.min.js', 'src/utils/jquery-debouncedresize.js', 'src/utils/raphael_free_transform.js', 'src/utils/jquery.hotkeys.js', 'src/helpers/browser-feature-detection.js', 'src/helpers/html5-helper.js', 'src/helpers/utilities-helper.js', 'src/player/constants/player-error-code.js', 'src/player/constants/player-event-type.js', 'src/player/constants/player-message.js', 'src/player/loader/base-loader.js', 'src/player/loader/http-loader.js', 'src/player/loader/ws-loader.js', 'src/player/parsers/base-parser-metadata.js', 'src/player/metadata/metadata-manager.js', 'src/player/metadata/localisation-manager.js', 'src/player/widgets/widget-base.js', 'src/player/widgets/base-button.js', 'src/player/widgets/time-label.js', 'src/player/widgets/play-button.js', 'src/player/widgets/pause-button.js', 'src/player/widgets/fullscreen-button.js', 'src/player/widgets/volume-control-bar.js', 'src/player/widgets/progress-bar.js', 'src/player/widgets/label.js', 'src/player/widgets/jog-shuttle-button.js', 'src/player/widgets/channel-volume-control-bar.js', 'src/player/plugins/plugin-base.js', 'src/player/plugins/plugin-base-multi-blocks.js', 'src/player/plugins/plugin-base-simple-block.js', 'src/player/plugins/plugin-binding-manager.js', 'src/player/plugins/plugin-manager.js', 'src/player/plugins/captions-base.js', 'src/player/plugins/context-menu-plugin.js', 'src/player/plugins/custom-control-bar.js', 'src/player/local-storage-manager.js', 'src/player/media-type-manager.js', 'src/player/media-type-dash-mpeg.js', 'src/player/shortcuts-manager.js', 'src/player/base-player.js', 'src/player/player-html5.js', 'src/player/media-factory.js', 'src/ina-player.js' ], 'build/js/<%= pkg.name %>-plugin-watermark.min.js': [ 'src/plugins/watermark/watermark.js' ], 'build/js/<%= pkg.name %>-plugin-overlay.min.js': [ 'src/plugins/overlay/spatials-data-parser.js', 'src/plugins/overlay/draw-base.js', 'src/plugins/overlay/draw-rect.js', 'src/plugins/overlay/draw-ellipse.js', 'src/plugins/overlay/overlay.js' ], 'build/js/<%= pkg.name %>-plugin-text-sync.min.js': [ 'src/plugins/text-sync/component.js', 'src/plugins/text-sync/text-sync.js' ], 'build/js/<%= pkg.name %>-plugin-captions.min.js': [ 'src/plugins/captions/captions.js' ], 'build/js/<%= pkg.name %>-plugin-timeline.min.js': [ 'src/plugins/timeline/default-configuration.js', 'src/plugins/timeline/base-component.js', 'src/plugins/timeline/focus-component.js', 'src/plugins/timeline/tic-component.js', 'src/plugins/timeline/zoom-component.js', 'src/plugins/timeline/time-axis-component.js', 'src/plugins/timeline/cuepoints-component.js', 'src/plugins/timeline/segments-component.js', 'src/plugins/timeline/images-component.js', 'src/plugins/timeline/histogram-component.js', 'src/plugins/timeline/visual-component.js', 'src/plugins/timeline/timeline.js' ], 'build/js/<%= pkg.name %>-plugin-editor.min.js': [ 'src/plugins/editor/plugin-metadata-list-editor.js', 'src/plugins/editor/plugin-metadata-block-editor.js', 'src/plugins/editor/plugin-metadata-items-editor.js', 'src/plugins/editor/plugin-metadata-item-editor.js', 'src/plugins/editor/plugin-metadata-items-ref-editor.js' ], 'build/js/<%= pkg.name %>-plugin-progress-bar.min.js': [ 'src/plugins/control-bar/progress-bar.js' ], 'build/js/<%= pkg.name %>-plugin-storyboard.min.js': [ 'src/plugins/storyboard/base-frame-position-calculator.js', 'src/plugins/storyboard/plugin-storyboard.js' ], 'build/js/<%= pkg.name %>-yt-player.min.js': [ 'src/plugins/yt-player/yt-player.js' ], 'build/js/<%= pkg.name %>-d3js-player.min.js': [ 'src/plugins/d3js-chart/plugin-d3js-chart.js' ] } } }, sass: { options: { sourceMap: false }, dist: { files: { 'build/css/<%= pkg.name %>.min.css': "src/assets/sass/main.scss" } } }, webfont: { icons: { src: 'src/assets/icons/*.svg', dest: 'src/assets/fonts', destCss: 'src/assets/sass', options: { font: 'ajs-webfont', stylesheet: 'scss', syntax: 'bem', htmlDemo: true, autoHint: true, hashes: true, relativeFontPath: '../fonts/', destHtml: 'samples', embed: true, engine: (grunt.option('engine') || 'fontforge'), templateOptions: { baseClass: 'ajs-icon', classPrefix: 'ajs-icon-', mixinPrefix: 'ajs-icon-' } } } }, clean: { build: [ 'build', 'docs', 'tmp' ] }, copy: { build: { files: [ { expand: true, cwd: 'src/assets/fonts', src: '**', dest: 'build/fonts', flatten: true, filter: 'isFile' } ] } }, // qunit: { // build: [ // 'tests/**/*.html' // ] // }, watch: { uglify: { files: [ 'src/**/*.js', 'src/**/**/*.js' ], tasks: ['uglify:build'] }, sass: { files: 'src/assets/sass/*.scss', tasks: ['sass'] } }, browserSync: { dev: { bsFiles: { src: [ 'build/css/*.css', 'build/js/*.js' ] }, options: { watchTask: true, proxy: "localhost" } } } }); //dev grunt.registerTask('dev', [ 'clean:build', 'webfont:icons', 'copy:build', 'uglify:build', 'sass:dist', 'browserSync', 'watch' ]); //Default grunt.registerTask('default', [ 'clean:build', 'jshint', 'qunit:build', 'uglify:build', 'sass:dist', 'copy:build' ]); }; ================================================ FILE: LICENSE ================================================ Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ Amalia.js ========== Metadata enriched HTML5 video player Download and documentation are available here : http://ina-foss.github.io/amalia.js ##Build project For building the project execute the following lines: ```sh $ bower install $ npm install $ grunt ``` The amalia.js library is in the build directory. You can also have a look at some examples in the samples directory. ================================================ FILE: bower.json ================================================ { "name" : "amalia.js", "version" : "1.3.3", "main" : "dist/js/amalia.js.min.js", "license" : "MIT", "ignore" : [ "**/.*", "data", "src", "samples", "tests", "Gruntfile.js", "package.json" ], "dependencies" : { "jquery" : "~2.1.3", "raphael" : "~2.1.3", "jquery-ui" : "~1.11.2" }, "devDependencies":{ "qunit":"1.14.0" }, "keywords" : [ "javascript", "library", "annotation", "metadata", "amalia.js", "player", "html5" ] } ================================================ FILE: package.json ================================================ { "name": "amalia.js", "description": "", "homepage": "http://ina-foss.github.io/amalia.js", "author": "INA", "version": "1.3.3", "public_site": "site", "engines": { "node": ">= 0.11" }, "license": "MIT", "licenseText": "/**\n * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA\n *\n * This file is part of amalia.js\n *\n * Amalia.js is free software: you can redistribute it and/or modify it under\n * the terms of the MIT License\n *\n * Redistributions of source code, javascript and css minified versions must\n * retain the above copyright notice, this list of conditions and the following\n * disclaimer\n *\n * Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission\n *\n * You should have received a copy of the MIT License along with\n * amalia.js. If not, see \n *\n * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n * A PARTICULAR PURPOSE.\n */\n", "repository": { "type": "git", "url": "git://github.com/ina-foss/amalia.js.git" }, "cacheDirectories": [ "node_modules", "bower_components" ], "devDependencies": { "browser-sync": "^2.11.1", "grunt": "^0.4.5", "grunt-browser-sync": "^2.2.0", "grunt-contrib-clean": "^0.6.0", "grunt-contrib-compress": "~0.13.0", "grunt-contrib-copy": "^0.7.0", "grunt-contrib-csslint": "^2.0.0", "grunt-contrib-cssmin": "^5.0.0", "grunt-contrib-jshint": "^0.11.3", "grunt-contrib-less": "^3.0.0", "grunt-contrib-qunit": "^0.5.2", "grunt-contrib-uglify": "^0.7.0", "grunt-contrib-watch": "^0.6.1", "grunt-contrib-yuidoc": "^0.7.0", "grunt-ftp-deploy": "^0.2.0", "grunt-html-build": "~0.4.1", "grunt-sass": "^1.1.0", "grunt-webfont": "^0.5.1", "load-grunt-tasks": "^3.5.0", "time-grunt": "^1.3.0" }, "dependencies": { "bower": "^1.8.14" } } ================================================ FILE: releases.md ================================================ # Release notes ## 1.3.3 - License changed to MIT ## 1.3.2 - Fix ENDEN/ENDED - Change player html5 class with base class ## 1.3.1 - Add edition plugin - Add control bar with new widgets - New Documentation ## 1.3.0 - Delete dependencies bootstrap,font awesome ... - Add Metadata Java library ## 1.2.3 - Player with timeline, text-synchronization, caption and overlay plugins ================================================ FILE: samples/ajs-player.html ================================================ amalia.js - Metadata enriched HTML5 video player

Player

Player options

src
URL to a video or audio file
poster
URL to a poster image to display before playback starts
autoplay
boolean, automatically start playing the video on page load
defaultVolume
75 by default. This value is overloaded by the volume set by the user which is kept in a cookie
controlBar
parameters for the control buttons (see below)
plugins
plugins configuration list (see below)
framerate
controlBarClassName
controlBar
tcOffset
mediaType
thumbRootDirectory
crossorigin
shortcuts
$("#container").mediaPlayer({
    autoplay: true,
    src: "http://www-player-i.ina.fr/medias/demo/audi.mp4"
});
                

Control bar options

...
...

Plugin options

...
...
================================================ FILE: samples/ajs-plugin-captions.html ================================================ Amalia.js

Samples

                        dataServices :
                            [
                                '../samples-data/examples/json/amalia01-text.json'
                            ],
                        list :
                            [
                                {
                                    'className' : 'fr.ina.amalia.player.plugins.CaptionsPlugin',
                                    'parameters' : {
                                        metadataId : 'text-amalia01',
                                        level : 1
                                    }
                                }
                            ]                      
                        
================================================ FILE: samples/ajs-plugin-editor.html ================================================ Amalia.js

Text synchronization plugin



================================================ FILE: samples/ajs-plugin-overlay.html ================================================ Amalia.js

Plugin Overlay

                        {
                            'className' : 'fr.ina.amalia.player.plugins.OverlayPlugin',
                            'metadataId' : 'tracks-amalia01-1',
                            'parameters' : {
                                style : {
                                    'fill' : '#000',
                                    'strokeWidth' : 1,
                                    'stroke' : '#000',
                                    'fillOpacity' : 0,
                                    'strokeDasharray' : '- '
                                }
                            }
                        }                 
                        
================================================ FILE: samples/ajs-plugin-text-sync.html ================================================ Amalia.js

Text synchronization plugin

{
    'className' : 'fr.ina.amalia.player.plugins.TextSyncPlugin',
    'container' : '#myplayer-tsync-tsync',
    'parameters' : {
        metadataId : 'text-amalia01',
        title : 'My title',
        description : 'A description I may have to put here',
        level : 1,
        displayLevel : 1,
        scrollAuto : true
    }
}                 
                                
================================================ FILE: samples/ajs-plugin-timeline.html ================================================ Amalia.js

Plugin timeline

                        {
                            'className' : 'fr.ina.amalia.player.plugins.WatermarkPlugin',                                                
                            'parameters' :
                                {
                                    backgroundImageUrl : 'images/logo_ina.jpg',
                                    ratio : 50,
                                    placement : 'c',
                                    imageWidth : 300,
                                    imageHeight : 298
                                }
                        }                     
                        
================================================ FILE: samples/ajs-plugin-watermark.html ================================================ Amalia.js

Samples

                        {
                            'className' : 'fr.ina.amalia.player.plugins.WatermarkPlugin',                                                
                            'parameters' :
                                {
                                    backgroundImageUrl : 'images/logo_ina.jpg',
                                    ratio : 50,
                                    placement : 'c',
                                    imageWidth : 300,
                                    imageHeight : 298
                                }
                        }                     
                        
================================================ FILE: samples/ajs-webfont.html ================================================ ajs-webfont

ajs-webfont

ajs-icon-account
ajs-icon-add-whole-segment
ajs-icon-amalia-js
ajs-icon-arrows-h
ajs-icon-arrows-v
ajs-icon-bell
ajs-icon-building
ajs-icon-caret-right
ajs-icon-cercle
ajs-icon-check
ajs-icon-chevron-circle-down
ajs-icon-chevron-circle-left
ajs-icon-chevron-circle-right
ajs-icon-chevron-circle-up
ajs-icon-chevron-down
ajs-icon-chevron-left
ajs-icon-chevron-right
ajs-icon-chevron-up
ajs-icon-chromecast-active
ajs-icon-chromecast
ajs-icon-circle
ajs-icon-cog
ajs-icon-cogs
ajs-icon-comment
ajs-icon-compress
ajs-icon-control-backward
ajs-icon-control-fast-forward
ajs-icon-control-fast-rewind
ajs-icon-control-forward
ajs-icon-control-pause
ajs-icon-control-play
ajs-icon-control-rewind
ajs-icon-controlbar-compress
ajs-icon-controlbar-fullscreen
ajs-icon-controlbar-pause
ajs-icon-controlbar-play
ajs-icon-controlbar-settings
ajs-icon-controlbar-volume-left-off
ajs-icon-controlbar-volume-left
ajs-icon-controlbar-volume-min
ajs-icon-controlbar-volume-off
ajs-icon-controlbar-volume-right-off
ajs-icon-controlbar-volume-right
ajs-icon-controlbar-volume_max
ajs-icon-controlbar-volume_middle
ajs-icon-download
ajs-icon-eject
ajs-icon-ellipsis-h
ajs-icon-ellipsis-v
ajs-icon-eraser
ajs-icon-expand
ajs-icon-eye-off
ajs-icon-eye-on
ajs-icon-facetime
ajs-icon-female
ajs-icon-github
ajs-icon-information
ajs-icon-jogs-backward-0x
ajs-icon-jogs-backward-1x
ajs-icon-jogs-backward-2x
ajs-icon-jogs-backward-3x
ajs-icon-jogs-backward-4x
ajs-icon-jogs-center
ajs-icon-jogs-fast-backward
ajs-icon-jogs-fast-forward
ajs-icon-jogs-forward-0x
ajs-icon-jogs-forward-1x
ajs-icon-jogs-forward-2x
ajs-icon-jogs-forward-3x
ajs-icon-jogs-forward-4x
ajs-icon-key
ajs-icon-legal
ajs-icon-list-close
ajs-icon-list-open
ajs-icon-lock-close
ajs-icon-lock-open
ajs-icon-male
ajs-icon-microphone-off
ajs-icon-microphone-on
ajs-icon-minus
ajs-icon-music
ajs-icon-picture
ajs-icon-plus
ajs-icon-power
ajs-icon-refresh
ajs-icon-remove
ajs-icon-reorder
ajs-icon-screenshot
ajs-icon-scrubber-cursor
ajs-icon-search
ajs-icon-sign-in
ajs-icon-sign-out
ajs-icon-sort
ajs-icon-sound-link-off
ajs-icon-sound-link-on
ajs-icon-stop
ajs-icon-transcription
ajs-icon-volume-down
ajs-icon-volume-off
ajs-icon-volume-up
ajs-icon-zoom-in
ajs-icon-zoom-out

Usage

<i class="ajs-icon ajs-icon-name"></i>
================================================ FILE: samples/css/amalia-js-demo.css ================================================ .header { margin-top: 80px; text-align: center; } .page-footer { margin-bottom: 0px; padding: 20px; margin-top: 40px } h1.title { margin-top: 25px; padding: 0px; padding-bottom: 0px; font-weight: bold; font-size: 40px; border-bottom: 1px solid #eaeaea; } h3.title { margin-top: 40px; margin-bottom: 20px; font-weight: 500; border-bottom: #eee solid 1px; padding-bottom: 10px; margin-left: 10px; } h4.title { } .smallpre { font-size: 12px; } .navbar .nav>li>a { font-size: 14px; line-height: 22px; font-weight: 500; text-transform: uppercase; } .navbar-brand { font-size: 24px; } .contact h1.title { margin-top: 0px; border-bottom: 1px solid #eee; padding-bottom: 10px; font-weight: bold; } .navbar-header .navbar-brand { background-image: url(images/amalia_Logo-unique-white-mini.png); background-repeat: no-repeat; padding-left: 55px; background-position: center left; } .docssidebar { top: 100px; } .download-version-text { min-height: 120px; } ================================================ FILE: samples/css/default.css ================================================ a { color: #008cba; text-decoration: none; } a { background-color: transparent; } * { -webkit-box-sizing: none; -moz-box-sizing: none; box-sizing: none; } body { font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; } .container { box-sizing: border-box; color: rgb(34, 34, 34); display: block; font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 21px; padding-left: 15px; padding-right: 15px; } h1.title { border-bottom-color: rgb(234, 234, 234); border-bottom-style: solid; border-bottom-width: 1px; box-sizing: border-box; color: rgb(34, 34, 34); display: block; font-size: 40px; font-weight: bold; height: 45px; line-height: 44px; margin-bottom: 10.5px; margin-left: 0px; margin-right: 0px; margin-top: 25px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; } pre.config { display: block; padding: 9.5px; margin: 0 0 10px; font-size: 13px; line-height: 1.42857143; word-break: break-all; word-wrap: break-word; color: #333; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; } .footer { clear: both; } ================================================ FILE: samples-data/examples/json/amalia-simple01.json ================================================ { "localisation": [ { "sublocalisations": { "localisation": [ { "label": "A demo label !", "tc": "00:00:30.0000", "tclevel": 1 } ] }, "type": "fake", "tcin": "00:00:00.0000", "tcout": "00:01:00.0000", "tclevel": 0 } ], "id": "amalia-simple01", "type": "fake", "algorithm": "demo-json-generator", "processor": "Ina Research Department - N. HERVE", "processed": 1418900533632, "version": 1 } ================================================ FILE: samples-data/examples/json/amalia01-ball.json ================================================ { "localisation": [ { "sublocalisations": { "localisation": [ { "tcin": "00:00:01.6800", "tcout": "00:00:03.3600", "tclevel": 1 }, { "tcin": "00:00:05.0400", "tcout": "00:00:06.7200", "tclevel": 1 }, { "tcin": "00:00:08.4000", "tcout": "00:00:10.0800", "tclevel": 1 } ] }, "type": "segments", "tcin": "00:00:00.0000", "tcout": "00:00:15.0000", "tclevel": 0 } ], "id": "ball-amalia01", "type": "segments", "algorithm": "demo-video-generator", "processor": "Ina Research Department - N. HERVE", "processed": 1421141589286, "version": 1 } ================================================ FILE: samples-data/examples/json/amalia01-events.json ================================================ { "localisation": [ { "sublocalisations": { "localisation": [ { "label": "Start", "tc": "00:00:01.6800", "tclevel": 1 }, { "label": "Ping", "tc": "00:00:03.3600", "tclevel": 1 }, { "label": "Ping", "tc": "00:00:05.0400", "tclevel": 1 }, { "label": "Ping", "tc": "00:00:06.7200", "tclevel": 1 }, { "label": "Ping", "tc": "00:00:08.4000", "tclevel": 1 }, { "label": "Ping", "tc": "00:00:10.0800", "tclevel": 1 }, { "label": "Pop", "tc": "00:00:12.0000", "tclevel": 1 } ] }, "type": "events", "tcin": "00:00:00.0000", "tcout": "00:00:15.0000", "tclevel": 0 } ], "id": "events-amalia01", "type": "events", "algorithm": "demo-video-generator", "processor": "Ina Research Department - N. HERVE", "processed": 1421141589279, "version": 1 } ================================================ FILE: samples-data/examples/json/amalia01-kf.json ================================================ { "localisation": [ { "sublocalisations": { "localisation": [ { "thumb": "samples-data/examples/kf/amalia01/f_25.jpg", "tc": "00:00:01.0000", "tclevel": 1 }, { "thumb": "samples-data/examples/kf/amalia01/f_75.jpg", "tc": "00:00:03.0000", "tclevel": 1 }, { "thumb": "samples-data/examples/kf/amalia01/f_125.jpg", "tc": "00:00:05.0000", "tclevel": 1 }, { "thumb": "samples-data/examples/kf/amalia01/f_175.jpg", "tc": "00:00:07.0000", "tclevel": 1 }, { "thumb": "samples-data/examples/kf/amalia01/f_225.jpg", "tc": "00:00:09.0000", "tclevel": 1 }, { "thumb": "samples-data/examples/kf/amalia01/f_275.jpg", "tc": "00:00:11.0000", "tclevel": 1 }, { "thumb": "samples-data/examples/kf/amalia01/f_325.jpg", "tc": "00:00:13.0000", "tclevel": 1 } ] }, "type": "keyframes", "tcin": "00:00:00.0000", "tcout": "00:00:15.0000", "tclevel": 0 } ], "id": "kf-amalia01", "type": "keyframes", "algorithm": "demo-video-generator", "processor": "Ina Research Department - N. HERVE", "processed": 1421141589291, "version": 1 } ================================================ FILE: samples-data/examples/json/amalia01-overlay.json ================================================ { "localisation": [ { "sublocalisations": { "localisation": [ { "shape": { "t": "rectangle", "c": { "x": 0.2, "y": 0.5 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:00.0000", "tclevel": 1 }, { "shape": { "t": "rectangle", "c": { "x": 0.2, "y": 0.5 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:01.6800", "tclevel": 1 }, { "shape": { "t": "rectangle", "c": { "x": 0.2857142857142857, "y": 0.3 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:03.3600", "tclevel": 1 }, { "shape": { "t": "rectangle", "c": { "x": 0.37142857142857144, "y": 0.7 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:05.0400", "tclevel": 1 }, { "shape": { "t": "rectangle", "c": { "x": 0.4571428571428572, "y": 0.3 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:06.7200", "tclevel": 1 }, { "shape": { "t": "rectangle", "c": { "x": 0.5428571428571429, "y": 0.7 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:08.4000", "tclevel": 1 }, { "shape": { "t": "rectangle", "c": { "x": 0.6285714285714287, "y": 0.3 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:10.0800", "tclevel": 1 }, { "shape": { "t": "rectangle", "c": { "x": 0.7142857142857144, "y": 0.7 }, "rx": 0.03654970760233918, "ry": 0.06510416666666667, "o": 0.0 }, "tc": "00:00:12.0000", "tclevel": 1 } ] }, "label": "EllipseWithBoudingBox-1", "tcin": "00:00:00.0000", "tcout": "00:00:12.0000", "tclevel": 0 } ], "id": "track-amalia01-1", "type": "visual_tracking", "algorithm": "demo-video-generator", "processor": "Ina Research Department - N. HERVE", "processed": 1432288449928, "version": 1 } ================================================ FILE: samples-data/examples/json/amalia01-text.json ================================================ { "localisation": [ { "sublocalisations": { "localisation": [ { "data": { "text": [ "This is a demonstration video" ] }, "tcin": "00:00:00.0000", "tcout": "00:00:01.6800", "tclevel": 1 }, { "data": { "text": [ "with a red ball" ] }, "tcin": "00:00:01.6800", "tcout": "00:00:03.3600", "tclevel": 1 }, { "data": { "text": [ "ping" ] }, "tcin": "00:00:03.3600", "tcout": "00:00:05.0400", "tclevel": 1 }, { "data": { "text": [ "pong" ] }, "tcin": "00:00:05.0400", "tcout": "00:00:06.7200", "tclevel": 1 }, { "data": { "text": [ "ping" ] }, "tcin": "00:00:06.7200", "tcout": "00:00:08.4000", "tclevel": 1 }, { "data": { "text": [ "pong" ] }, "tcin": "00:00:08.4000", "tcout": "00:00:10.0800", "tclevel": 1 }, { "data": { "text": [ "ping" ] }, "tcin": "00:00:10.0800", "tcout": "00:00:12.0000", "tclevel": 1 }, { "data": { "text": [ "... the ball has disappeared !" ] }, "tcin": "00:00:12.0000", "tcout": "00:00:15.0000", "tclevel": 1 } ] }, "type": "text", "tcin": "00:00:00.0000", "tcout": "00:00:15.0000", "tclevel": 0 } ], "id": "text-amalia01", "type": "text", "algorithm": "demo-video-generator", "processor": "Ina Research Department - N. HERVE", "processed": 1421141589288, "version": 1 } ================================================ FILE: src/.jshintrc ================================================ { "curly": true, "eqeqeq": true, "immed": true, "latedef": true, "newcap": true, "noarg": true, "sub": true, "undef": true, "unused": true, "boss": true, "eqnull": true, "browser": true, "predef": [ "jQuery", "$", "fr", "google", "_PlayerAmaliaVersion_", "_PlayerAmaliaHomepage_", "Raphael", "MediaPlayer", "Dash", "AudioContext", "YT", "chrome", "d3", "nv" ] } ================================================ FILE: src/LICENSE ================================================ Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: src/THIRD_PARTY_LICENSES ================================================ Third-Party Licenses : -jQuery : easy DOM manipulation framework, MIT license, http://jquery.com -jQueryClass : simulated inheritance in javascript, MIT license, http://v3.javascriptmvc.com/docs/jQuery.Class.html#&who=jQuery.Class -jQueryUI : user interface stuff on top of jQuery, MIT license, http://jqueryui.com -jQueryUI Touch Punch : touch event support for jQuery UI, MIT or GPL Version 2 licenses, http://touchpunch.furf.com -jQuery knob : a knob for jQuery,MIT or GPL licenses, http://anthonyterrien.com/knob -Raphaël : a vector graphics Javascript library, MIT License, http://raphaeljs.com -Bootstrap : responsive design library, MIT License, http://getbootstrap.com -Font Awesome : iconic font, MIT License , http://fortawesome.github.io/Font-Awesome/ ================================================ FILE: src/assets/fonts/ajs-webfont.afm ================================================ StartFontMetrics 2.0 Comment Generated by FontForge 20090622 Comment Creation Date: Thu Jul 2 11:16:15 2015 FontName ajs-webfont FullName ajs-webfont FamilyName ajs-webfont Weight Medium Notice () ItalicAngle 0 IsFixedPitch true UnderlinePosition -51.2 UnderlineThickness 25.6 Version 001.000 EncodingScheme ISO10646-1 FontBBox 0 -109 1000 876 Descender -2147483648 StartCharMetrics 98 C -1 ; WX 1000 ; N uniF101 ; B 127 156 898 805 ; C -1 ; WX 1000 ; N uniF102 ; B 260 88 740 662 ; C -1 ; WX 1000 ; N uniF103 ; B 162 416 838 658 ; C -1 ; WX 1000 ; N uniF104 ; B 379 199 621 875 ; C -1 ; WX 1000 ; N uniF105 ; B 186 199 814 876 ; C -1 ; WX 1000 ; N uniF106 ; B 234 199 766 875 ; C -1 ; WX 1000 ; N uniF107 ; B 391 343 609 731 ; C -1 ; WX 1000 ; N uniF108 ; B 207 312 793 762 ; C -1 ; WX 1000 ; N uniF109 ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF10A ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF10B ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF10C ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF10D ; B 206 351 794 723 ; C -1 ; WX 1000 ; N uniF10E ; B 314 243 686 831 ; C -1 ; WX 1000 ; N uniF10F ; B 314 243 686 831 ; C -1 ; WX 1000 ; N uniF110 ; B 206 351 794 723 ; C -1 ; WX 1000 ; N uniF111 ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF112 ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF113 ; B 137 204 863 870 ; C -1 ; WX 1000 ; N uniF114 ; B 162 247 838 827 ; C -1 ; WX 1000 ; N uniF115 ; B 215 252 785 822 ; C -1 ; WX 1000 ; N uniF116 ; B 209 246 791 828 ; C -1 ; WX 1000 ; N uniF117 ; B 162 246 838 828 ; C -1 ; WX 1000 ; N uniF118 ; B 162 246 838 828 ; C -1 ; WX 1000 ; N uniF119 ; B 209 246 791 828 ; C -1 ; WX 1000 ; N uniF11A ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF11B ; B 234 244 766 830 ; C -1 ; WX 1000 ; N uniF11C ; B 306 246 694 828 ; C -1 ; WX 1000 ; N uniF11D ; B 109 -18 892 765 ; C -1 ; WX 1000 ; N uniF11E ; B 106 -18 888 765 ; C -1 ; WX 1000 ; N uniF11F ; B 60 -69 941 812 ; C -1 ; WX 1000 ; N uniF120 ; B 55 -68 935 813 ; C -1 ; WX 1000 ; N uniF121 ; B 104 -23 897 770 ; C -1 ; WX 1000 ; N uniF122 ; B 43 118 859 819 ; C -1 ; WX 1000 ; N uniF123 ; B 141 106 856 807 ; C -1 ; WX 1000 ; N uniF124 ; B 148 118 862 819 ; C -1 ; WX 1000 ; N uniF125 ; B 74 119 927 820 ; C -1 ; WX 1000 ; N uniF126 ; B 148 118 958 819 ; C -1 ; WX 1000 ; N uniF127 ; B 141 112 856 813 ; C -1 ; WX 1000 ; N uniF128 ; B 15 113 986 819 ; C -1 ; WX 1000 ; N uniF129 ; B 76 115 917 817 ; C -1 ; WX 1000 ; N uniF12A ; B 186 247 814 827 ; C -1 ; WX 1000 ; N uniF12B ; B 209 294 791 780 ; C -1 ; WX 1000 ; N uniF12C ; B 427 271 573 803 ; C -1 ; WX 1000 ; N uniF12D ; B 234 464 766 610 ; C -1 ; WX 1000 ; N uniF12E ; B 137 295 863 779 ; C -1 ; WX 1000 ; N uniF12F ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF130 ; B 162 283 838 791 ; C -1 ; WX 1000 ; N uniF131 ; B 162 319 838 755 ; C -1 ; WX 1000 ; N uniF132 ; B 162 295 838 779 ; C -1 ; WX 1000 ; N uniF133 ; B 258 205 742 869 ; C -1 ; WX 1000 ; N uniF134 ; B 210 254 790 820 ; C -1 ; WX 1000 ; N uniF135 ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF136 ; B 0 0 0 0 ; C -1 ; WX 1000 ; N uniF137 ; B 760 360 887 594 ; C -1 ; WX 1000 ; N uniF138 ; B 595 306 906 610 ; C -1 ; WX 1000 ; N uniF139 ; B 345 247 887 708 ; C -1 ; WX 1000 ; N uniF13A ; B 114 190 887 760 ; C -1 ; WX 1000 ; N uniF13B ; B 162 27 860 401 ; C -1 ; WX 1000 ; N uniF13C ; B 113 190 906 760 ; C -1 ; WX 1000 ; N uniF13D ; B 111 207 904 777 ; C -1 ; WX 1000 ; N uniF13E ; B 111 204 882 774 ; C -1 ; WX 1000 ; N uniF13F ; B 111 372 238 606 ; C -1 ; WX 1000 ; N uniF140 ; B 111 337 422 641 ; C -1 ; WX 1000 ; N uniF141 ; B 111 259 652 720 ; C -1 ; WX 1000 ; N uniF142 ; B 111 207 884 777 ; C -1 ; WX 1000 ; N uniF143 ; B 21 -45 975 818 ; C -1 ; WX 1000 ; N uniF144 ; B 173 210 827 864 ; C -1 ; WX 1000 ; N uniF145 ; B 75 207 913 788 ; C -1 ; WX 1000 ; N uniF146 ; B 71 214 908 795 ; C -1 ; WX 1000 ; N uniF147 ; B 282 271 718 803 ; C -1 ; WX 1000 ; N uniF148 ; B 186 271 814 803 ; C -1 ; WX 1000 ; N uniF149 ; B 306 205 694 869 ; C -1 ; WX 1000 ; N uniF14A ; B 239 223 761 851 ; C -1 ; WX 1000 ; N uniF14B ; B 282 223 718 851 ; C -1 ; WX 1000 ; N uniF14C ; B 234 464 766 610 ; C -1 ; WX 1000 ; N uniF14D ; B 210 223 790 851 ; C -1 ; WX 1000 ; N uniF14E ; B 137 247 863 827 ; C -1 ; WX 1000 ; N uniF14F ; B 234 271 766 803 ; C -1 ; WX 1000 ; N uniF150 ; B 210 223 790 851 ; C -1 ; WX 1000 ; N uniF151 ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF152 ; B 275 312 725 762 ; C -1 ; WX 1000 ; N uniF153 ; B 210 295 790 779 ; C -1 ; WX 1000 ; N uniF154 ; B 176 335 824 771 ; C -1 ; WX 1000 ; N uniF155 ; B 16 -109 984 859 ; C -1 ; WX 1000 ; N uniF156 ; B 186 223 814 851 ; C -1 ; WX 1000 ; N uniF157 ; B 210 295 790 779 ; C -1 ; WX 1000 ; N uniF158 ; B 204 295 796 779 ; C -1 ; WX 1000 ; N uniF159 ; B 306 271 694 803 ; C -1 ; WX 1000 ; N uniF15A ; B 0 323 1000 875 ; C -1 ; WX 1000 ; N uniF15B ; B 0 645 1000 876 ; C -1 ; WX 1000 ; N uniF15C ; B 210 247 790 827 ; C -1 ; WX 1000 ; N uniF15D ; B 11 -105 986 858 ; C -1 ; WX 1000 ; N uniF15E ; B 282 307 718 767 ; C -1 ; WX 1000 ; N uniF15F ; B 355 307 645 767 ; C -1 ; WX 1000 ; N uniF160 ; B 186 268 814 806 ; C -1 ; WX 1000 ; N uniF161 ; B 186 223 814 851 ; C -1 ; WX 1000 ; N uniF162 ; B 186 223 814 851 ; EndCharMetrics EndFontMetrics ================================================ FILE: src/assets/less/ajs-animations.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ @keyframes ajs-hatch { 0% { transform: rotate(0deg) scaleY(0.6); } 20% { transform: rotate(-2deg) scaleY(1.05); } 35% { transform: rotate(2deg) scaleY(1); } 50% { transform: rotate(-2deg); } 65% { transform: rotate(1deg); } 80% { transform: rotate(-1deg); } 100% { transform: rotate(0deg); } } @-webkit-keyframes ajs-hatch { 0% { -webkit-transform: rotate(0deg) scaleY(0.6); } 20% { -webkit-transform: rotate(-2deg) scaleY(1.05); } 35% { -webkit-transform: rotate(2deg) scaleY(1); } 50% { -webkit-transform: rotate(-2deg); } 65% { -webkit-transform: rotate(1deg); } 80% { -webkit-transform: rotate(-1deg); } 100% { -webkit-transform: rotate(0deg); } } @keyframes ajs-bounce { 0% { transform: translateY(0%) scaleY(0.6); } 60% { transform: translateY(-100%) scaleY(1.1); } 70% { transform: translateY(0%) scaleY(0.95) scaleX(1.05); } 80% { transform: translateY(0%) scaleY(1.05) scaleX(1); } 90% { transform: translateY(0%) scaleY(0.95) scaleX(1); } 100% { transform: translateY(0%) scaleY(1) scaleX(1); } } @-webkit-keyframes ajs-bounce { 0% { -webkit-transform: translateY(0%) scaleY(0.6); } 60% { -webkit-transform: translateY(-100%) scaleY(1.1); } 70% { -webkit-transform: translateY(0%) scaleY(0.95) scaleX(1.05); } 80% { -webkit-transform: translateY(0%) scaleY(1.05) scaleX(1); } 90% { -webkit-transform: translateY(0%) scaleY(0.95) scaleX(1); } 100% { -webkit-transform: translateY(0%) scaleY(1) scaleX(1); } } @keyframes ajs-pulse { 0% { transform: scale(0.9); opacity: 0.7; } 50% { transform: scale(1); opacity: 1; } 100% { transform: scale(0.9); opacity: 0.7; } } @-webkit-keyframes ajs-pulse { 0% { -webkit-transform: scale(0.95); opacity: 0.7; } 50% { -webkit-transform: scale(1); opacity: 1; } 100% { -webkit-transform: scale(0.95); opacity: 0.7; } } ================================================ FILE: src/assets/less/ajs-webfont.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ @font-face { font-family: "ajs-webfont"; src: url("../fonts/ajs-webfont.eot?93a8957d9da533b23877909fab6d8fc2"); font-weight: normal; font-style: normal; } @font-face { font-family: "ajs-webfont"; src: url("../fonts/ajs-webfont.eot?93a8957d9da533b23877909fab6d8fc2"); src: url("../fonts/ajs-webfont.eot?#iefix") format("embedded-opentype"), url("data:application/x-font-woff;charset=utf-8;base64,gAEwAwAAJSFQUy1BZG9iZUZvbnQtMS4wOiBhanMtd2ViZm9udCAwMDEuMDAwCiUlVGl0bGU6IGFqcy13ZWJmb250CiVWZXJzaW9uOiAwMDEuMDAwCiUlQ3JlYXRpb25EYXRlOiBUaHUgSnVsICAyIDExOjE2OjE1IDIwMTUKJSVDcmVhdG9yOiByb290CiUgMjAxNS03LTI6IENyZWF0ZWQuCiUgR2VuZXJhdGVkIGJ5IEZvbnRGb3JnZSAyMDA5MDYyMiAoaHR0cDovL2ZvbnRmb3JnZS5zZi5uZXQvKQolJUVuZENvbW1lbnRzCgoxMCBkaWN0IGJlZ2luCi9Gb250VHlwZSAxIGRlZgovRm9udE1hdHJpeCBbMC4wMDE5NTMxMiAwIDAgMC4wMDE5NTMxMiAwIDAgXXJlYWRvbmx5IGRlZgovRm9udE5hbWUgL2Fqcy13ZWJmb250IGRlZgovRm9udEJCb3ggezAgLTU2IDUxMiA0NDkgfXJlYWRvbmx5IGRlZgovUGFpbnRUeXBlIDAgZGVmCi9Gb250SW5mbyAxMSBkaWN0IGR1cCBiZWdpbgogL3ZlcnNpb24gKDAwMS4wMDApIHJlYWRvbmx5IGRlZgogL05vdGljZSAoKSByZWFkb25seSBkZWYKIC9GdWxsTmFtZSAoYWpzLXdlYmZvbnQpIHJlYWRvbmx5IGRlZgogL0ZhbWlseU5hbWUgKGFqcy13ZWJmb250KSByZWFkb25seSBkZWYKIC9XZWlnaHQgKE1lZGl1bSkgcmVhZG9ubHkgZGVmCiAvRlNUeXBlIDAgZGVmCiAvSXRhbGljQW5nbGUgMCBkZWYKIC9pc0ZpeGVkUGl0Y2ggdHJ1ZSBkZWYKIC9VbmRlcmxpbmVQb3NpdGlvbiAtNTEuMiBkZWYKIC9VbmRlcmxpbmVUaGlja25lc3MgMjUuNiBkZWYKIC9hc2NlbnQgNDQ4IGRlZgplbmQgcmVhZG9ubHkgZGVmCi9FbmNvZGluZyBTdGFuZGFyZEVuY29kaW5nIGRlZgpjdXJyZW50ZGljdCBlbmQKY3VycmVudGZpbGUgZWV4ZWMKgAJTiAAAdD+EE/NjbKhan/77ULS7JzAqWmP5MohOGL9RU602BTA30cbNBClK9qNWEtuRCKyFFMtcSoRplxt1oJ+eZiBosGhUkOqMc/LeL7vPhdFauTheUp2rFaQNQIAC6I0MEH9xG8Zr8PLpL93GsYj5HutrhgUNUDLmq8sR40PG15Uhe1lzly6ZqUIGUazzuP1MrR2ksAZCrQd6W4YkD4nyvAEQCcss8XP/aOmojwAY8YfV4Db+jZBPIRhC/wGqfKrd655aU0+j+Qvbj2/+JPesbnvQp0zynrulGHHw0f8yYuo8r/WDXk9F79Jb/XTE/zE1BoRlrBX9K70+kXin8UkAGHSlu/REKQqRRHWPBeVaZVWnock7t2Ty5mk8j+gh8KdhlJnz3a3RFoPdenLxu8jQqesIRvkwEZAg+UXf1TUmXLEFBsv4os/qUdiS5r4feeQil6w04/ky+jh8o79KkpyGDXYQJ9PFuEWFzp9gVl2emOaALVr7NbF3oOxsCU41MUVN2Uo0OIkjcFBETaK4b2j31ok1cSCh0q25HMRwI30aSqdqUHjVdOktH8w7LfVPr0qNa4R8ZyERTXiqajyU2xdFqGf3QrSccHl9uLlqwN05nKRkSpAZkgRNfAhBWJyIiM+wVvanQJzOk55g6LRF+bAJZra56hk5a2k83hBYqRZOlSW5oO4qwOhBr5R4B6MEmd71uCx4E1qwxXSEZLb0OycmQsjDM69c6l72bTHgudawTsnUQyvP6pSzEQGL6fwRi5gYjgLJIovpI5GYLCEnattrimGAZPs7ORlbC6jP/dIgUTlqM+tWN2NsQ0ddcLCS5j8vYqeFD/xnvQCT1B22xQVQpJX1yhfvz3j2r4+bpvBMjFa7FEweDB1BKtgWw+mZldYdrWQW9JEmt716BU4j8a0LAMuWaW6Lj8LTbIN9qWaUeMxotTlaL8nugrHeor7/s77+PTaN0/30Kh44njo6YD3MveqHXdx5X4W25V3hiBFVmUlKxbxxJiT3o6NJWVTvlQpPW4z9cg2fPxKhcHcFB9xF4XQLPRMin3HsGxG4NvizASKdKbrMQza39IKH8SwGapHBL2CHRcdsAYOcpCJxcUTQd9rlJHseaZ38LgD9cGgV6aRcZAt2nrzQaNTbt1Cv4MJdjRE8HGXMryauqWzscuC3JGmLHCTNnqqcz9J2q12fs4Fx9ZWL1qS8UKaGSHwfhkBYxwJ7eb/37QZfQ+ZhOWU0imlKRLFho4qA+wStJe6MjZ01VdZq9pOpQrlj3AxTTzelGr/162IbpgOMMsZDZyEG4xZyoD8vyKkmI2FIWFyLFy2BpJvlKMgC54tKM5Ymo+EfdaTK55628THulS/sdUDT3uR+UUZyKWSO9926wHO/7wO7Eg/D7jK9BDZAg1MBiS9enITCRIncnWUGrq23hIWHzOoDeryzin3L02wgOLgZ6awfAf6K7+YfbZ5OIwLzj9TVQNN+bxCSg+pfDiE/wOO6REyXQj8lcWqZk1Tnh7qiyl+zZJo5Ec6sFIaVyNGIUocw3TVGW7dV5fjuUY79DtVX6cW+Z4cgepc24AG5D9btV3fF7wHuweAhgs1QKqvnYWUIGuSZ56DnZZJU9jvZskHFg6HKirG+OT8lJZSg/kXNgMT9Z7z3piG9Nbpuy7TvCTjHTqnYCMK/iu2+c5ErVKv3MQiuRb+PJ6F83V7mkttvlx1iZhEgQq/Egx4+7faropWdAuDuwPs/ZDTWp9ud+Ya4pUEhLXH/kv4xihr+Lx0k2M8BjLazV4vfVbgYsLKRhK2FwvQ4sCoawHkHeH6MgYfC9Mg0PPjqH2XTMSu8GTUAq4cFv8lifICs0FJukJPfzzemtcuc6/piz5rA17LfxDa5a0aC/Fb1m9YB2qUOCYqY0cTiROPasVWd+p3G1bt8oJIDzQW6GLAkbyBpQaDW+w7TIWdtIRfFcc7UIpUcY0PkXSi2R6ZBRdK55roytCtKks9BEDZ87VrMOcOtwPtKpuoKXVma42CrwLA+YoxUjrhQFVKo+POzjzwwsvZT86avheAexZKx406R0JRSWKKyAh5dqaymFsHnDB89mSpwH+7PnrLLfthrGZVXN8iKpPG1TyX8YFf41NWaTgUM2cuowjSHzp8EFLELIPY3iPyrYA0Ilr5wdTmEs9cQLLK6cDHBUXss1ZZ5+Gz/wzaaNeuTiUv06zHXZc9iLCfO9h+HKgGBa0DedotSEL7f/KG3eAyjp5ScIysWu+TnYonIqRKCwiWf++bYYnqNV6JzLYl1SWDDDKgUxOcoPpZlh5rleiEXrUaXaCNbIyNia2yU/mVZioisz3mwws8gmNxLDgrd2oPqwceyy60YAKgBtZnGGwhKK5IenTel0VV1okUTb+u4FJnGH6fMBBUnV9FJbpXRn5JKnHEzDbRG9/Vyx6AWrkWnv5Kh39qxks++mqbn2dUD6lzMxQJyvsnfJghiEal8YcuTFCOdXMGdV3HEW3IZLF1gMRm+l48qCqE0LyOvz77XtoJPJMdi7wwCm5BiTRZstJMf7DCYfSqtlc/uxLCDZvSW0frT+lFs5sUqq8q8FjlAFE/NLdpVgPh59jEZX04QSxIRp29j0SxeOr1haeiBriaGvQjOaWy1rmq74czogsZuWIJrInpLndQjd+SU8DDpMRjT/N2BKycrFoIpzFF2vB6XTR6moxSvHpvmMd0aihwI9a2nxd7GUjGI3qZjrHg/FLccq6nHXm94q0IeDNizQhu1JVIr5zYLrnHGKAznN3m8c5EUtvr11dQTKo2OXDmaIN+8WoE/C/WtEWwEMKrtSTfrq5Ury8tyI+j02zlD/9cBPRZnlICuyVDvBbdxfDKhjOkrYk5da4rpaMp6O36fjzpMtPo7zrvrU5qj/iygLYxdH1K5p0bEw88CsQedyeFDeORIPU6WDLkslLDBTxEYKJVq4OwNpc7uqxdX7XYsaB5E4OjTXqI25UAOBwCgBNAqSrysyR9vMg5Xt4BNhLBck88RydgjIROJ+ULDHsXIWK+pUxY2fgDkEC+AL4UYcxU99R607YSktrObFqhTxImk14K0Ism7nydvTK1pAik+bI4APCIr1TL3y9q6p5Rxol02/FTAizzkvu30NyJwmd8zBtiPy604UpOnWTk0HJa8w052Gy/EqXeTIiM6rrUOngH+X9p/w5HbHC2wk5osknKSr5kMtFpM+U4Xsbcs3IZ56wzqjxOMbogPbTV13r5VRaS8lpvCH4qv8CqOcnLbcaqb4QA/audoZ24gcEJLZEHJdnlF4tDivV18ch58DnBKIeI0CSKOv+RI02oDycne+aY3bqr08PX19jWVMDZLzSU/b+LQQPyQuvOCnkbtMakc3SvfhKg5/6zygGwRoEoFfOmPdV8SCIdqi30uJ6uP9gHIhL6N+sjT9hApoQSXOOkbp6USmLSmdCSGPq9pIsriT022tL9QFY/zCScp3xQd8mk2U8QQboTAfWvzcaFsFRiNlm1smvi7e+3tqZ/FVEUXUL5LsmQcgav2zvEqYpVqfhg6uXwbYzKdADgtqxpLobbAZsS6lOinvx7G756DusIamAknW+zDHa8Qtjv4BNEILWnWI4ms16Rl5q/Dts+P20vktgp8cx1rvmk/uT2z4L5arIcdlZ+E+XYpyjyFpmnoFWGLM16j4d6ZmWYM3lJAnkzxPs43cVH0voJugumayFh7t9dGwzhwqIATjG2uyHRkcWO7qmmYC9kDhyBkmyHIZF78a4hMWiVtdMfis9qmvaNd8MNpBKV7CRipbJ9pYHc6bN4P2xNUmtlpTWHfxliga12cyNe6QInBeMKdS++0j/szTBJrBvE1EUrOEsLNIUf24OeBIMv8jWnRrfsxmt1kpdqZ7nyv3oBtU7tDZV1oAJQzpVz1JdG0tsFlgsWk+H52VUfbYqcCD++21bfnjA7+gWr5QElTDjgjFB5sLS+N/2viN47NSQ/BfWpyEdq7MnPuTRRCdFl+W9og43gK17jWP82jX+AZASj4nHWkD9mxMpClpURiGvRrWN/sRMJr4n8YT8Zv6OlpCngBvn8dT7+H2U0Oq+Y2Ao3oUjPPmbxx9ysMEKu1bO6fDfAGtsK3lP7a7KQ2vzVk6NVT3Q8nYRaIOxFcKJfUmXYZeeZGIPXrdZcPqsRKYp3bIz7lGZ+LckBObPWwgO+13b5I/aWU+hYIj4Q0Oa9BIDuAh7h/EmgQ9d7VHaWQy8ab/+YzN+vze+Oj8iyvfFXGatiVSgBybVUh/rK64vQX+SZt3BwGldz7IwtIKyV4UsSAdfxUwRu/TxdR9VS2fCUF6XJrK6px2ZbI3SnKZxFIw9AorVVCiD435LMb3E53XQvLXf/WrvBbZucAhf0igzELhlea+ExdvTZ/c4ISIr+3X3vAeb41Ux8j9fxtPijmk/zQpMG4+s2+0woNs5QjiN2eU1iUHlYcB1wJtYqp+/0NaQCU6R95SuqczH9CbaAhA8wjEVAVvgsmVTpDCZ3HYtCr+dj4QuPTXOhPx0CSKwNYnI3cFw/K7x3rZ022bqb2CnXMSgmmwIUc+pliOo+7dST2NdMlc3RG+bKfGiZFwQRBRyPdMgGHk0MnzeZRM3diuAaYDLsK9VafedqJn5Lx1LIIE89YXFUvnVaEcl4Rj5dikbSXuyljWJj/DuqgAi7pNaTTB9q8ag5xy7Kj8OSjAKdT0NMdCbC91xfUuPH4fi1pw8ovs3X3r+eZQ9gxGtNK1yDKorVaMK1dsB/qvMaGiDYXJLiq/plwLPas/jxico2I/mPOlJP6QhLXaKVpyRm7MS/vOGLhZjTvVg8dl5HMFLgL2VRS1oT3ExpZBSbc7hUDzx6lKjGwkDZ9XGlutKvB88+I/HLnFYxUjhmiu+nJCGflI0UourMwmgUbHUarvtC0afm0XyWjG29gQvIHjvjbDVnShgSTuGSjeYnta38HXHACQip90PzzGvBGU+uBUVtftKsKGA1de6VX5j7qxytYxcrkjTguQtA1e4ChIWhPLjAhVK4E+qVtd/b5ZMUNdqw3CGAjTXiQIfCoMBMH8/jrPtb4KrUrE/2h2z8FPaXkRRN9RvY0l+6kkGAZKiC+qN/mRGMY9kxn0fjtmX8zuWTKfIIEgaFKb77Op6KH9MXfHckW/y9dvM+gQW6OVb2jF6lQyzgDttpMRdtWBnUeOE93XVagW3AW1EsqqOkd90j1OUhL3LXoNzrfncOcLmhZ4GovaVCiEZt1z8kNp+cxd/7nsiLyaA7A+Tgf/HVmhupcqBmwWosZ5FfAiZ1BRnNIJpZIR1PnXr70bZve2LhUNpQwPrIDRUxerVEPagN8FOzDNgXcpYimI76e5jNsp0f9YqnDUGzgUQoSp/kizLcJ4Ijubcy5WYPRANFsApgdUL0r5xAZ1TdHrIvlDdZ1Ki4ilAzGmn6pVT7YvVuv4RfAhy/6Dn0SrIwbOdlttarn4r4A2aHesJi4sZduCnc+o3FdDoLgGUYnnh6UoT0lMdbBuoaVztyw8uJG6lkcF0jUolOL+aH+JtNMN5IEcuq8u5d1z/6iaNflEAAEEl5ifG8WM/5nRWOaFla0ogBInB52REp+2Yw1m/gKDiO5POepbIT901JF+u8PBR1+QE/rXX3aexuUyU4bTs+PuzWtXSchmbINaEBfKogRr6bOJPlsGnqD4bx+qSak4oyrLzZvVB8jIGcxutXwIxWVS2V3VS0Ec+nL9xP/uyK5mS18diHPFx8gNfoZIcpxkZ4KqG//sxCf4Qj6+P1OtzYA5o6PmwGZV0C8+gW7Zmt0HY0CgxZb6O4hQvZTGJF4sIqByR0YhH61QT2h5kqm4hPBP+wfzDRlJBpEbS+enQwDrs4z9pKZWzPh5uPQtSaVNwcIWQEVCQGmE09C0y+HYTUvvkjynZWNUM31cs8ArJpJHlyKCs/95BM+2ikRd/H/4Iq6kjP3CizD2iCOx9ZT/JNo//UMnAmpXdvw819UErxTXYVUy4QsWQkLGQIUmQIzHTrW5oIO2KKPzn3SzSrpVgZ4ZMuWl4nu4X2YYq8hAUHHAqV7siTKtj3Ph/fTudQV9Kf8BmmNLeNc3iuRKPKLYYbHMYbZBIn8otHEvHkEaZx6YwBTd+GrwdfFfGhCcJGyjDswRWm/scVPkL0OamjdRYtaAxvr3y3JS+tarJXCKg3Ebd+Leif2n5or7ukKcCY8aHlWVa65Z22VGaQWbYF7Js5DL5CON3myTNqR8NoYtaZS8BQX3hkewOQpvTaUSWIbdZL0Vvyb/Qm4dI08BBrI/1MklytGu+22bIi/vRXXv0Ov0q9jxvUiechZ9YOh99V895obzKr1bmSGRCZu2l8aZuBO/OQ836GBlxHfiwu7B1HQIxq+qmEDghOvoj3FxkmVewoxFzJHc+lqdCy5qbWQJKNJxYs15IKGO+eP6ynpaOT3gG9rN22VUIFcmGSsKlQgHkv2m9RmzGINIfWhNnRBAxb5i2I5fD9y/6e05vDuv61SQtJfyuqP1++vKxkWLp4WWAygDdB7MH95OEe6L3cXmTnFX/txXkoyoT5kNH8jmEHi2KeCNoLyZfY8/3sAZehcEqK7r7iM3LHJQeMguqalfPuOVnQ+WbqOtPc5lHo056gdGg6oY1fAp1HG4CP47NyvX5roZA/NQouf+5g5Ryb5imaI8WrdkUKqnNIPG5gX+zvnKEBbh4SJXC486EPAZzSiA8aZh/d4ciuWRt69A3Aup8AreVx0io7uELrV0M8JsM/CxHv6u5SLxQCNfZALim/VrfUHFLIvBRENFJ58ZdGgfQSjP+ZCQYmM5APn6/eYWtLk/9xk/q0DCoptuV0g5Topq2pXcml/wVJCGDvzX9I7kd61oTUIIFhFC6p1Ws7behbYqD4x62+r0mYM/tS1u9CNKn4oh/xEBAkXQWXcDnevjBjYh3oF9hD5wwd9DZjqbPnZknKHh4z4FHBN7dwD3w75ogB1+NykRc/3odS3I6+BAJc/1tE/2+qDARDz4iGx3oyx+8LlUmpQrIx4iAYop3B27gGA0cPic98w+hb42682DP6WnMb2lN5EPtsmNUzxV1EW6u+iH1yIBZR60ab7oaEKyk/uvvpSTQlG+L4UTWBZjxCcLaaUuc6IhDcoskxcHlDwppfHg02GqBfMWBACDsiweh+DcC2j4oguYv2Un5ycbuhZPh7LEFLbZTrBTJXEmNTrawZn2zQwSjaos+l/5be0X7mcnJmwcAvSh8K5W4CJ8ON0XiPpv3EhV4Z44KyGP6H/msTD/usyxDKQACDv0EdmeHTvzkYnBXD0MBxdrTFE/8TKKE1uwZTmnTtZQOl69euYhQg1rQPuxEgOoUQyv7iBY5xr8MZCsbTcZ5rG9LltV9svWlCzf9jy5WNJOGYqoDDvkHBWOK9/KguwB462vIfPhG59F4Ixs9oGEOk/bG0ITm195zUr9O1veFMs7i00HqtWNHde23JjjT+B8QB37pM9GkZQ/4KyCFL+Oxk/eFAsQAv8mNZTlJBfRx+/IQRdFx1E57UlPcEThp9HlS+CBaEgffGpV6p6Upm+3GRFbMVVqJ7PGeLyhwFxSR4eE4Gc9qBAYiH+I/SD6qXoyV3rbVdvgqvQ/dUBPHicT8NirBP5TQ3xKQf64X7t6LZY9WUh5IDpJnIz99Fjrzy0JZnsZZUMuY0yt/eQ0Mnf6Xhsqn5kCvj69BuNLy7b9yv5lGEo5vx8trFkoMd6DAfdEQe2/I8Lw7x807yV51Wwy3LMtzaa7SoXs/6TmdolcA8SaOTZKtxKuP1J6IsDqkdPpGUIjPKqOweBUfne4JOCWg59v17JyvccUxi1kP8zpkTHjmKfoM/z0SJFstsCNcpK1YNHHR1hjM/SI5Qf9uSqK77UI/q/X2RP9niCdiUkQw74oWVpF31rHHziPOfzj1yPMDTgUn9cSYK00+jcw0TKA8khCxDSjxpRgK7bbAsnk5J3IjAf+UHGv7RDuaOxc/a6xCt1YArkZ1+3pPfoQN1T36+lYSJZUMw8X4zD7hTcJw78rh5WE2bWWPbFggsKbpDIKXr6BeZ82WxXaKGiIwTS4tb15AACDS0UO34eHf+nAYiVthftk4U950UZWVrxF8tsCDGDzF7cvb76xBOizlcqyHgpP6ZH/8rb+xWxPvwxAdfN7UPFanZfUeQUEfrh/4oL2TYxWxcyRDPLNXhzsYqVXi87QOaoMr4iMspUtpGd0RTs6qV9iMrEBmUoAM2CEIAzKiqgsWOdFzsH3oXJ8zno3n/vRGzSrR5uIu4DiAGXOCEV/QwuMlvvUw7VjcHqkJ1QIC1koFhg0JMNfM4CvxWzF+b37w0lLFQF/ZVD0B4jSJC1jGqcFPPnEVYnt5gML+CsscRwAmRzWxtMehgmP4RBIeF9aJJP+BTE4CL9NBIlNLpyVqLTapKv1ADS9mLgKBmiuesPdPhqUc+XIlT8Kai5zdh7llhdYULt7eOU0/+1dDXZHLzzk8tJ4Ll14HuN9DcYTzRnOd2qc86XANsI263NBHqQH5NFrrsE1Xj61HN5Z35/Ec3kC9rjHHidaqHjR8kdVMEnIzODxQSDI+S4IefpoADnswYbtlmd3jCghd5yV94LxRV6DjY63Sajvk05D+TxeQMWSrahmAbU/sZvi8NJ0jJdb6rDwpCa8hsz5vOIVcbwBjhbbAKc0jsaUQrHQ0m7/DxiAry5iS4BR6JF7gvtUG2u7yKvJKOTt1z4rebfHRPDW0vTzcXyaXi2bFFQ9qKaBiEw/Iyl5v22gnY3qAN/WY3MPjs30LCA55UiGLF9bZuPIviaT5pLuoqBbJy6HDwxlyI8mKaAJoBizOnQFT6yR37FlC7rypuN1aGAabgdsm1Y64LoZzT/nCabbOCz5dXkuJY99DvNDWRUAEE9rITCGwWJtnTzb202vpyReIJsk4/v0GRJ8qq+IrvhrO6LAqEZcHi//17jLrgLEQSl+VwTVMMHVZYEgPAeWiWmhGQ1VtYM/FWNYVGN1WQUCqtMl4QVbRxWNBihMkHNGBMMrJDFwbCZKc/PNdd6Wejnf2wjfyL/R7h2VEz0qqL/suWz/rXTVkAIHWlXUuPg8xvBbpy9iCJLJel0WNegA07dqJbWB1xHT8JQ1m/6SQ7yvoGCAz8RkjuznJ+/Frj77iALfIqoFUoe+Aun/d3yQCbtHQaDncPcSZIN3MVk4o1XFAmjhTbzmo2HuJa/2FjrUIvwQkVMNexKxG2JNspF8lqc/+hFp7pcSX85Um4CDjaYDLFpRTBb4U47XI2N6J4vyJ3l1FjRxpRWGy10vgksPJny6nCSwzpwxQ+/rvYKP0r8dWNotRbHRjRb3v40hpI5EYPBsZpdULpkj6NpHsHYp2CAYS2GJpQaaqkdUuBp6UYL5EZNk76xbc4do1x2QO7/LKW898Ba/udm/VDCjtOeSbvzt/DrPEYl5yVJszH5nYqgukXR22PnWsHMHe5+P7ck7Y0/Rl2BmJSRBtbQQJZKS+OxediAkuAVWfQ2Wl/kv+PfaSLO2+2WVduLlsKk+VR1E6VXKr7cKyvd1Zt57ug0wtVXnXJ9rR6WfVIHGlIxExd2ySj5ZsnQ8uWdpVECGyD43masvq3GNzpVaBLW4Jta2TzCGKPhFL3qmFd1JgLI2z3G1osgUKyYW0hg0ndIPEIvy8cyCeup6XxgGnGHtwr+t7HCk2j2zp0T2MC5RIFfg3tpmN4PXXqHugXQX0bJZSqSS/mmiHTICje8Lp4SFynkA+IGb/YhismZqLR4BNimrhktJFv2b5Toa9CXbXDjlxljhGYEWAzcCwfp+ciHwAS81+L5D92rd/I54Q7MrVAZGOermppge7RrRWcv8tSD6hspTqXXrL/HPETYwa81k9Pi46awFOm2MlS3u6xoxtwbr5vRlLNH5wRXsJofWyWl/YBS0C5F5U1QKzeG0Ri+kNc3rDzf/CBS7m4Rc7000/WTbEm/u3LKKZEfXPhaGD0DlbDlv5QUw57unrJc+QsIu+vfZJ/nJxNOuJmEpvEIZ055Hhd/5axfhw83WE29qo8lPXRFdcg75Dn+D8bvVY4Gvv0cu5ks1DsRAKz7Ju0/EAQUTDCgGdkTAYd+S3ai8ni9S946KrLwNX7llHVzxgCNCQHDMdet/C+ISU8Kvozx4gZQsPGe1MbReOugmNNEF1kC1atumKGhzw/zBD8wA0TzLvxmviL6jPsMrVOXBp6Xl+rOk6QwubZYb8RwD2ktR6cxVCJzfjGk2cmW4/whVJtVTkYSLtpFG1dB0nE5cNQLsSHZ+jTYmi+z1sT1jjKhkJSDQ0xPhDakg3DojUDtXGqSv4K6/GZlJju00xUbtgGCjEagSX96zRVx8Y+4rKLdPdCaLbdoBAnenf+tQ40GR+evI0jWIpLNXibOE6Y6d4XQDD5b+vM4f6S9HuIxhagXcxwIsPK+ZpFQm+NiCnA1NchM1jnlYbtPW4PC4hsaXGvqmi6Dgh4rJEz3FPO5mcUlvMgeokP1b9AHdzynqngXXPlcmgA/++cp9/exrnnzGTuXerZ1d2nvJlDtJXQFN12SR9yrmBPCp06vyvefJcIlCyrmug3EcBl5V0ms/IG0rDg5zkz5aIF70t1l7Rvz3noTpFArkozDU2ZR/DnbnU3pbzf2g6TCTL9pO70uxxaxzNhZdNem/MUFFnz8ms4lmsUu6lYauffrAzAZN+/Cfah9VcWxtmiiizrZERSq0+9E9rBuNrusOGfler/vdoifJ+paMnyMyDj9vrqE9atBk3EpLGUVEeiLi1WLb5q2fIr1AWKN9sdCYlLlMpA1Kwp4/Ykprzb8bT62ms+SoQ3ki8hNIO1lx4cVdfS+LFOQeSF0DqEies8D6YkdL1S4TOhFF3ylykUPkr+8ShphGJ+9JXF+X4hIdNHXuIB+tIZq2rUU450ImEZOPZrAkz9pufAi0P1Ua5JmUdrLCrlc01zX8OHUmExZDbfuFCwjnZyU0sTl+ccKCa+y1s5pIyjVXTZZ41sDIyRWQNO/TWjxqFussDeFN0CXltoEhKt1/gREvLILuWg9XCUr7RpTgSYbZufP24/JO2nd1r+3SyNweyEgBSaF0+qGu6OFJyIKc9QPwS7YBLEVkHX2m7czLWEM/NLuUoqfLaetx2/pvMcGPJ6PouN0/blaA88y7VdVEf2+aviVn9B7VLUSRuxYRS/qz9OHbCL9zEh9R8JK5LQ7FFEhfoDevw1zuYzYh+lSxUkgLrTBUY8TWRW4igkCvCqOXZ8fmpXvxxtabG739FHOuEVzbvmdlUS34mXMnnR3YVVy06uc7v2IjH0qiyQDrZASCRuU4ZmcjR+/vFVFxsHvTuhAqSsSQUViA4KII2ZRwzts3AM86PMGtEsgUDvLGuhJlSKnq5CGNN78AuMPmkyWZC6EZ1psHryhLt5xSnu2/KNYOTDUcFLfzN0GTqm/hFOQj5sI1z1ez49SJv+COVXDrse3oaa8cPZAvkUp9UcW5dwyHof2zADmYNtP7xNdpTpNCoAFd5XNtz7vviUZFHBEsU+2SfOy+2iQjtquQ0AlYgIgjT/3yZVziwgrM7ZZHFKGpFpvoJbN32rjfMID2M+0dTcKXZdLXDNNMy+gJTLMoPwDMgsrSpPSX8C11x6jGp7/JC8UbXCsM9rHHPr/p0Z5H1IhyT/y7/fbNzHRRZN9NTXVWTpiVPW/62Aom4aJXNZQDuV3F8Kf7gpOMBxfzdLScybsIcRqlJtpomFe4NzdE1xFkNabEFrwEyiLPdJHIfTCkHle0cpEJ8zKl4nKosCRNCCBQsC5EI+96kEcao+OLHXp4qIEu6VB3S7VcQyO7d2wwmlFxAkrdQ7/Nct/KddUYw5ck57D4U23MWHwRr+UbqdAgMA/oWnW3VBDXqAevSRiEAVHoMD1ia+sgFl4MUASgWgr5KUqGIYZ1Og/Q5BLlr83unXmFZpZe4ZjBLTqD5DTi6NUWi3A8sapj6RlmQ+fIMRzXwmx3mdwH9Z6s70qeftQyEJP0C9QYnM5FmK9mll69hqUQgJlnsp2SMjrAlvxiINudOZWMFJjWDnVBnP7vAwFp6KFtPwzqLYD9aXJmYiuA4wGXVB4Z81Yy+w5o+7BTNDFDRm98y6Och5SLjseNCt8MNXSAU+Me5yEwWWLRexQHg+CIaKR4xuyLsnqYNfzvtk+Yq5mgrQIm2+8Xpg5RCNuAlifiBSQpol9VTXrl37P519grTKrJ8rgZIWatzj7HNP8lwqbQo8TAb677MFrhYxCwNNidqTMaqd0hIenCJVcimu1wrNfk69Z0LU1qf47oRArYg7MQx+3IQQx2SfXX/a5sJ9mq+u9BSZEBiss4NBWlGM55jDUrPX/dF05NGG96jhLO6JLI3mYKgsyJ9p7QQHvZ/xNwfBXSMDmBs98srN08ltCA3KAbpIRB7W1xqxjFS+EYr7Lxj+yZr1ymboYSBQWN6kkcctXEtjPdaNL2tH9AqjxFSkNaYc++sq396RlkuH6ow092xsCXHdSfWxRaBlaGmpjotcnjWmipdKj2wjAmjfYqkF4cwR9Gflz+0OQ9m/Q0S0cHIkLJa3BQMEeRXB3HbE5iwUkQwZrynj4IVSHtimDscH5nXYS1eA6p9Q7x7xkkQnKMcaL83c7Tx7EuKPCtOVYboPaKkw1PD3pnVQzRmWLjUVCjILQhbVtWgU9NMfPQrpbAnTuhAQO5WHWvsiyJVbm6gtfFYkMMD9mtQyRHR3jijco2gBczuMZTit4vWZJKjFhoxaP3x3GxkwgJ8SpNy3Nz82Ghzg1JlUNav9LxJeTOynx9q2ucHqP7iXrOcgGyzaSLcQrCgWZhPh2sJ8JjP0SFbhZ2/Q+4FJd0Kh2xKHOpNHC5LM5mlB3acLJovEzCisa1DGGgnPw3muVes+BW2C+S1/hCjp/V42D6ByIKxbfKmNW4rmz/ZGdzGEnKR/0y9AgjE1vlD+6+hvgz7YODDGvaZs/+d8rGvuVBRMvrl07Yx68n633dHhhNPA1lE2qZaoEHRYnkfP1R7rQ22CrwiZf7TpSQ4/bNIePYdGcE/laHvOwZHQII0KVALhOS11Y3qR1xAJTW/M9L1FIreQu/N789/mTwnUhfk3TBduKsF6gLIJkkMBrnpo7oQq2sAPb3/Ai8Y4OBJLkdBJwWdiYu8lXev2BDuY6P2+O0MoKhHFCX7z/RI2M9dfqWZJLzB5jHtPm6SUDiMkxi7f7EF/RS2oVyOqMIQKzcIAFaxloXA/0bPYroydmfdWQA9Ryrqww02Dayu9q2iazxWx43zuJdpwrPbu4KSJiJ8KGJ4G8qKv6Hpdm/LuTWqRBt49aTUrUtwy9uRVyeJAOav9XbXeR4+7PlkvDt71Vr6EgHoISVG1d3T6iIKoRQ4LDpPP8QdhB0YLsO4G9gzNJERVO0zamzdR4p84i+jK4y1q7PfhKHgNF0XbgtsFjSk3Ec+v5RsMK4Bj+L8Y3D6KL0c4eYifD2VM8CdsgKnaNNhx/7z28tRfZ6bovAc7bjLHu5bC5Ym8RWHiBTwxePJlr13PuR1e8gIFuWTUFPN2agiGM6c/ZOVJyZGjZ9xldgjVESvcqN2kMW/G+KPwrXlG1eBSrTASQK8rDImQysIwOU4H+6Q1oYZue4iyxWhh9d/xnnX6Tf2qV5d2xvxOcCQGGeSNfAgWuobL0TZT9dGAHAx5DFVnNqJd3Ble6yxXRcfx3jsiECJDwA39Fh+jRiNMrnEodc2cxQ2tYlJxax6cBdurg85adSuNvx71A7+dW/E+wyL0AK6u0g5QkqQwdefk4KqkD5hEwGSX+U9nAoOEJqwwN4qpKDhTXKcg4OEt/LioObJ88v1ohGvPjs+KDTw7NDBdX0Fhrp5nO3u1lhe4+F1obU189aHhiV7ydASZI90cM+LYol1hNtl2txbyxIK91PP5DZ4TNZwzYfBWn4Aktao6MUNo7f5096NCmNbfU3cZcuYraUKxrT38PfAOlIiR4WxikTHdG11SE81XrRO2IxL6A3IhCKcld/Ke6xt/se5YQEw+9a84Po9R3Q5Aw5IqQU8AYRoEbEGSbgbvLAlS9M7oMFCTViPt/wSQJuYrjXVSyzxq43nRRJq8WG2CAEINEDuJu1G3vxyZOSDEHl5svj/0MxMYRT4eSmo3TAbUKGzpM+GUlDeJEzMRt9N41cflOSwSGvp+rNyYYsfkGTzafZUul5WDVy4FUKZMzgmb4oJceHO49HPaYAF68SpobqoVsNHchO41AjSAybz1NPiUzEE8dShSj7GATv5Qo5tGm6IhDFVeRYTfTouHMS9BAxI5qkZnGEjoQ10cWyJb3sMEjtJPNHxx7rykzdCb4xvEZIwaF+XVe0bWiuQe0vkEL3jjOH94slE/Q/YtycrzvrXIdifbdMIVM4ESRxIZXRCmtOIcaNYfX35B6ffGcmZK+LyOfAt1Xx4C54bdIFMoDscp3HSMajQ4fxCEvOfEgG02hfRpuK+ib4gjS1gzQSM1yYzMaIiGbJHEIWcXv69RPbLgDMvntkEBUOB+ew/BCIDD0MfFZbcBJxwsFMR3xEt0+8ZYK5vKBXpVIME/ddA2fOh0Gve8Fk2WDPXWpUKQsnu2xZQoe4iBZ1CXGj9dKkh2wn7QOw+lNlmh/xFrTof4SRO2Y4VpM32iy5dZALAiLd8yCAXrHESSDk2mOYtL8dTKRD2rhEwM8jEpM8FsWh2ZJc0AFkFwKxj2ji9idCT2LIoEdhe4aLgIMY0D445LK6I3g37J/dR2+5Cd7qTMGqOp6PCIlG4uKo7Ez99L7H+vwJRvWZ+xrtE/KGgVHXwnoA5p04ttQwL0gOiGGe8Emr3mQfUdnddFB0S8ZZkLzBYkjvyb6UH8eG7p9JMQ/W+DkbvwxZsW3PNSWO8gL4cfYl6CqAzXDIktRgPh6MunUaygka1/nkQDR5lLUmi38JzFDzu+NnXEimz0yBsC1xOkScO/8Hmca1S73x6dRwNGZ6P3Q1azvbySi0OLm4qF2EOSZIYBiNcCfMsqiEa0d2Tu7DMlCHh4Ee2fGcYMY0jUN3naZ4BKa1eHXy8FXpB7WxqCFjo3+y93Fdia77o8orXPSYQXaTFNGXCfo6ZlLaEynFFDj+FN2iv6YZAaFbA7EVpnFT/48iS5u4apXgl1vSm6wMtdeauyzRhZZc4JY4pMXUBqocOnRdQhOIizu38Z78HYJ/me+hwOUcC1JLmnVyHKjLaQHjofi+tpLJi3M/77ntiR2fYz/kA4Pvs7EO+h6BJrZcX88JhOfXnf5tvARB4ajqzUhoB5Ob33ko18yPc1c4aU1o5wtkXsLhyGP38rh+rzlCbFU2q6HAat/WesC/FKw1YR0HAv+Tqd91myFdfGINfRh1SaEIofl/+qO3gNEDaenDx5y1SXF/PpfstBIysmIHF8vCpn48Ra5ZCUimJx6QR+5bdtMWVNIR0M0oMRpfjdr4dZBKzPeoB95SKjz1lE/ZgkivXsPYM7ym8OiKa1wIW+PxQo+aTIk8MmEwthd1crA8QGm+Wg+Nzl/O+3pEMaU3ydIK6/38W00Q4l/5i3fAuQNikb6Wmq1DrXc/AcqPhvHOEAd9AaiU9jUAr7E8R87FhcjrAY/TAxcuCcQ5BTghQkuttu1hhJ56jOpj7J2t/TYUNHXAcqeNQLsKKwUln8EvdMuz8NaBnsw2IyP49j0RBdOQO94tHy5CvrgQ5JaXzJH54YB0Ic7MmonNgyUPLM7T9kRBcnd73VAZo1wA14LfAyU+o1jxqXvYcK5udrSaCSCOTPnz10B4zLypJoQeuTM0Q9+xPWwiDOX8oYTNSqVwzyoGDits1YDVQd3BTWRc69XMP9Sp/xeLjDgH8qHH7ZKG5oSzzJAVHatWNa8v/oT8zkAIc2k106TplGQMZLmhBhtVQsWyxKcDargTo93ADCMMNXAoULDU3lDEzrF9H0brN3v0Q9np7ZUWMr1BxZwvx5BTFG8dIJrh3NaOLjPG/k46GJZXjFbZxiBBuCwx6ewQe8TPIq4XN76oByroA7oPjxWzDeAeZLREh8eOgrfxADmWe3nygqU6end5oNavjIjgfXA1pR6SAxf3sEDoNAyljVbGnKLRfinwAYHWjWxuIfIFBQbvmeAskyNJPg5XVmPLoprxzBwWG1Y2/5VwbgiI6fs2JQp4JDzgsWI/Y9C1lCOB6RCmwTyTfb3HA8Rw1h0YJ+XHR6FogY/yRHh2vU+zV7+b5AZSk3EskpZ3uCtV/yXB4YR6+39YNxm1jP42s2pR0YiWMFpC7fnpvT8B/HXYQn0lfXRdshS3hWpOdFyjTy7qB/vhPsK+N9HfRW7pDmgwx5y03xnnNbCJ6gHKPngEu1SsNF7hvT65dnshzOIYee7Av4/cMmyE7G0Ij0eCBdPrgnawx4NSf6p5kWCS6UXQvq13PVWqsEOAxUvxgMTNEgJbOYdRMxJXUn+ugUtZHBSOHJr2muBEzo8pBUUfnftMhqBSk05ls5fyTjWsbq63Ld2EIikJIEfF539uMfvLMNcmgutPs4ybzmhUQM+H3XwLPJuQhv3LEM1dVT1OI+4qGuGRYjzJqtetOEHjRS0dchunR9yxyQlBYycKJT6TIKOGzYH0h2xxIKPyf8HJSV0B4IGcZQFHiQyDwfVb+UPjIkOcLW89sse+tHez/kVd8hPmnV02Q2J3m5qan9OIUXAicAjfRTy76gtkq+80TFJi6QI3oHJLY3+geUuBW9mBJ2xEJ/PPtk7rO7xsPQ2g9XmEqlJ9mQ5AsLgKd+LqdZOEIAr7IhT7nLoXSAWmAbvRIbtxcOUGdX+UBlhrp+NnJMbuq6kDJfr6MLhN58kyqz4hfyp2iI4V2UQzHu5YbWaI1nY8YqwLwezCZ60Q1CE6Z3gsCeCR699LnLwETx2nzxECbYABOndl1OlVPiG+MKZjkHBnbG2ZmMP1zhrW5YeifTff16RW7i75oyuvILasI2m5MuDt8muK8b6Ko18Uj15n8Cjo1mhcAWL57Rwo0mBtpmWprtPkZ6+x+TOoWUYn9Cw2Mn+RtVCnE/6NZXjAPI6gbckvNtllPSt3EEHwaxpo0tflDToWQ/l93XuKHMc1bCPkEgaEJIu5cy/47phWizjyPNpblwgFGUOPHuCEuExAU/bPqu+2jmJgt5Qbxt7NDKzjX3bkIyrZRgoCaEYx6jJcA3o4pw1k+dTUOcssWpPnd2lt0q/fu1qWoguEGL7o0VCEO6riDHocBYuKnT8Gafps1fHnbDV8pCE5h9lZ50yey5KmMaG8scduSoo2PTgI90wsdPVAuLObsPeahgQTrh6fZ1QLsEG7xz7VMiwYrJQ/7dmEeLja9uKzzxW9JP0bGdViBcoTWnhroVZpUXtOgQawjhdXdm8/qFInY4i+Uv3o6LfuoAucEPcKiP8YlR1CKYRCVzY+sG0u8pCBRTTBUwWw44zgAddXNFKzxyygKlGmZZOR8xRDWEOrMBJ5aAVWs403BLIVrWk0r1yhj0OYU1lGgI57mzUWYC3Zma74OV/IEmGJuhN2Chvp1bQ6MNYkmsKY233Kbst/ZikCsuj5OyCh6GUJZ1+BNBdkMqtjQXGOi2cuQTj851ybBeCTl9nmkzGTFgjaMs/F0DlMZYrIxoZsV6CKLBYUKqryrxTK7rOI3+GK8njuaEy3sjxckK/6xuLwWJk2YbIfH43E4i/R+IkxkzWp/O/Jg2CqAxU2KqzRBBToHK5p9Bjr/ofYNm9+qEvYDqQcFMF7F5S0pRlUKdIJdJ1/17MXX8xHnNetc9jAuuYZxeJaPwCt4gmXN3zpQJ95WEryQpSx5lIwgX/QH4w3lKJXXfzuNLdJnpID4a/lKgiIyJRCEOFuyJA9OlsccK8sEpmtEWQa9pTGw+R+v4qKEGbLF9B7KGSqsjuqKWAuaztcSqdXsRAx1SKlbwtS++qIjQua8bWKqw27dsDRpE0u69A8krOmZmwXET4UzQnjcwJlZ4Ah3xzJLYyFiJGoEK9dFNoPXLU+oBg56pOhKcPTDzfdVecNab03MP2UQw6JkIo1T3NqK3Ma2WfhWBDcnYWVg19WIX9M6KCuB1jci1H+gES+zGCllE8kDck2U/jicKRO91k3YmwuUkFTMNJKfqZLnHate16pehR7K1RtRj6elAWzA9zWloCSyATP7IPK3rd+eiWy71gkoO38L80kOhcbffuXdyrpJf50y4xznOC1aBaeaAQ2dE0CJuGMemsNbLZyOWVuiGgKNlmduiBwm6xphrreNfpxNqT2jsbPim7hAf/XQTgt7IG12c3yBNEYOspAq3Tofqkqqx97TdXYAzmm9JXHra+LST5KuCe01LWZSv05KcUJ6+YTFAEFGa8bJ5/oka+ds4oWn2iYo70qMsKecsBJImrNBp5rQq4HUd+0nFeeEQOBVKR0ApsBesPumTUnZ9e2NB78Zn+W9gdLBLMx7MG6+GTqSiW6jjMI7/war+iQoLdnSj1plDHh/PNG/VWjPSaG+wew6TGKRB+zvhg1zabKYzyQqmiqX9hHPNLg90UxZxSTrNfuxbyazqNR47yT+DwK33ldXpAAZEEYvzza0lBD70ZlM/oJXnZkLNba3zXBgCJg9K0R1HOc6SEkfQPtt2ThyVYvUoI7EeTcdMNte2RYX1W96JU9FbvEmQqH4QcX4TcsUcCbpo6a+hKF4nvY0EvU8KeEYEt01uCvqZXAYuxxsq12mS6UxhBEA/bT3qCJtb833Axzp66gQYq+20ebOq/gsCVTH3/fM05l4vnVeMNTKYll6DnYLua+p8yqUG9ho8yf+Z0eUFE5al4Xwm4Ey2UV/T+Fk7+ZEh4X8fzN7z5rd7DS2+eO27dVdgeQg5gtonSUq3lLuy++jjgcVTCTsGaq6BLFFRpUNHWcIEvIaBfoTg+i/hU4fhSeiyf//PGKiRzCAKOwVjsx9Bv8xy8JcvirDYVV1ybMlyFh8y8oOSapGBzZjA5mHFDUtOUFZWR4dAicn/yckWh0zdnhDtGv58XXaS+ZJgqMvlg96XvAfBjx0lsAEeAUrnw/ZqD4d3eLhP03sZvejEHa6BTG78xwh7uXvsSj2YMfsFdx10dA46uShBR8gxM0OudIRLiJVPF2hzWkZSCAl+b54rj+puY+JoHwlEKE5dIfKFzUEmWS+LJ39pJIsYBBn+KwQAIwFq1vKy1CrcM0eWbKOJpfcpGf2H4anovYCnWt8+40SOsJ900lTv+QHac0moOcJI2Y8mzTryOk8GWCRIMbneMH1Ben3Q+h6a6K/8GSLDQGm/cp9BmGYUlppDKqCbJD0T6SempM3Ve1AhGv29i1qWk69CdDBLYps2SCrwTeHQ+bjD0Q4KrCFSmzgUckn+AZjN0CxHgg/z2BJFFJgct9kMCRWv67Hjnso1vx3bMUg4xnrXmdIiuCnxxdGCiyfX7Mf1yQ2/nshY+qH4mK3EEvYvgQQ3aRRyD+kjYAuEx9wrbSaoh6XZD3vVHkHkrtj+KhmbucT3FeNUe8kL0rWgDmKmMxTe56aaRVPNsZoXDpv9ijeveqNUSOxUnOBzbsaae/bb/9ix0HbOEctbpTMHejDHwKsIzk1a/k5GIdLGiUr1r6TETu7CePC0dv5RP2/c+24b8/Yd4nyngei5Apy4aLNwUkhCjzyuZkB0he5GUV2r8WODnrM3TMjPrzIkngPf5WSuGv299yNbNMzlV4xO/UNAR1mjkFUhSAvxIvlkD0mIf0/k33GX+Smcm52h+qxb7+Seefn0nzrGtz2uEAX+zOjwXVX6fU+9G6GUEr54n5Immy12CmM/Y7e7SHP/MNWbfqhMdBqdMeiu5abGqLp7NanDMxD1DX0Myh1Lk2GBFSweQrGWjVJI2P8AOHB/WqcqRFtdnHl6Gp5wdZxuNmsouTvEQpTYbyXpbkIJ3tT4tG4t69PnbGw1gtlTsQszOfPDNGqmb+TX7DfWtph0EKNdDICWyB8QSYajsBtbZgve+T2xkRpLAvA0YjrAW6PJEcEfz0Y5npOcEipZksHqxesb8fQjwCQYmf68R5dQWvon/TLQmuxzgbheUk1BvlaV5gN8Ldh1D2b9o6I/JUrWN3gpnllaRTP1jrb1olgo3GdJ2WZV1SV2RiJtf485mmX2343lTG8/gNx+XPBkzKaXc7aLMkxivssTzjI5U4jvfdKk0c0Uz08J2ySmYx3ZKxPDDD5bIeW0DmSMo2Emds0Ee2GQMhRHMmG/dNTAAT7LJNK9SyfXS+9pWoN+3nKMHac5JQvTILz4apMl/uUA6ObzKyk04BU+BVuyX/IFKMPAkzrqprsGP/V1hUv+3HC9TavCDRx8ZyxdkhlcQWkyiF4uynQ73pZC0xQoPb3wQkvCmFwn79FsZDitwPmzVjjXdQMXSeoAnlZDcwMWbRpXCB7/G40zoz8i/Vx2iu34zV/KcmRxFH6/Y9u2f/sTWp6NeryZROS1JCBqSPlUc/Ydi4GWZM0OHkPSyii7ecECCjlzaAs1iPwTIdsLVMhiFPoR0Fo3khBZrBRCyLcw0jpPcN3SToTLbiyrXVCggwn+CZenU/sE0SV/2woPZjdBqnZ8AOqOHK+sUKAARKIay5VIQcqz/Jur4rYz0UBM4dbKYjDlRNODBnVn76CMMolyPhFvRIaP7yxunLyuv4ZjaVTKERPpH8bEssSSwTHMjScbUc8HkfSW1kmyPekuKB+6KMObUw9yjaXshxJlSSzUC3xjwYKZsZQRGiGsRmJVug2Wd5BPcmK04NFr5K9mj+dulolOepWxbLQiGrZcsR/OSa6dpFZ1dTN6WxEG5zijRxiWHCZSL4y5aDC26mjAD3+na6gkBWnfsZ27ngHYznWUUmRkjGBp/nYIPGDEdphVUn2PNHrUT5N1q9+GwqbcRecsC7s7uHbZD3SmFCsWSl7dFhiAKmXrt5HCCwiWfRV8LgxoX6peaFHkAzMEGSniO64SWFtL8EMFAVNePRV++S7ZmGA/e+hCDMetnE8e9ESMBMT0Z3sGH9ZP6l4MtbERPwphjhyyX5K1O/wIOshFKM9CW9TNJokrUGHH5CZjjihP0upOW5DNmMXUeHZ5HXGZACGvbNYmuwwu8exFAe3EKRVDbwWvQQZEofmaRZ/YwHLyJKHC465qfvKy/XTMVowhfDOvKxSD+tqcEbuaF8jdsCS9ZlXuCR2GYxf6xt12nYuHFSO1emk9HA+AMeQ60K9EBcH4wPAnN93dPyy5HjhKqHyM5SCMdn2JSPly8/Mo80xU0ceFlJt93FQBOfkXk/npHqkWuECL/ii4kfVV9tAnYEFPTBzk+XRVon1iHfU5ycjs+cC8ME07APRXmIlE75UfxQ2Fa1HM8rp0d0XWyoLYyXH24aeV54uSmLY08QLmmusfSqUzIxMQDCZQoxc2wtnSFo/IW+E37fLLGGDnt/kC00f3GyQyOzgFeOr01tfbQp9kn7G4cwqmy+jJM92Vqd5obAY0G/RYFmKOAEXf8v3r0/sEexenhDLADA0TauA4J7f2IW9XZqxt4YHsjq51TM3cwbwg/jvbwdHT1c4ai8szQUswK9STtRIgOXKix+Nfc3IwYoZq+saL6QYzeOg5BKbQocleoIlJsJod0+U7HVyDuEbkmgO/zxEE5ybuPyBXrz5DOWoASheyYxpl8czFSAb7pSGuBkB8lFvYJ84ovucMtnzaduqqsERIZrF+KuZSoAZRVnw91lSwD/pLMsNqb/gu1VeomL9hRyGaC1tLyqy9xZCiEmxM9q2aSYUL0gjIbYPko8NVxHqxNPVGBOboA37wjgNNxVG9uPY1vbg3C/OCR4uimZ0lnECZYrFKQUUeyFl1nKdzHe/mMmXQ/rMcRbte8AhzL1ZK9Lpgk7Mqsly0oeP9lL7YEHSP6k76T/a2EB3gHX3mQH1PTyWY7RdwSQxiwjd+3VI0OahNm7fzpgQw9E/W+Y21kA/3yRj8nX5YjJJ4avGidwjRZ6K/RvfDwC84Ut83Nur66DUtIlEKi07O9bEAxzY5NTQ8+Od/RaLjeenLjKOO7bev3eiScAEh9+94FDmowOplHV1qr7cOPct54/FCi4bf6hE80TGW+zVj56BKoT0MvWcnYjezzzL6nNJu54l755hIJue3cnnUj2MgpBXP+b4KBo5uE0TZBiIpE+d1dtVDDkTxCzFEsP+bFyMjbEliE3g6AUTh2dlOugXxwwqjXuWpzfgX4CSkE6FHIp6C65mNliCUz3wHGnTyMjeV1ThG/y3kBW3EeN3PKXDr+Va0nIwtSOtOv7TyGVBR/Q0CljFuelLWb82Yym6RzLZCXkcRraX9se6fXoT4rB6qfGzuQInt3FZ172igpMTcMb+aOmsNBNsAkF/sTX8L4oUaKhVw90sXY1+vQAaJbi3gZmG/d2IBeT54yIrKi7ujCF0Cen9Fgz8YgENOwGNwrSVNwcsZrSnirPWLyZgApOEVgaMtKu6rxUZ9sCaUuc2bJGvLnoBMxxIcbyWyhwdtbcNjSQ/wl1oepN18DtMIWG/kmysWsadkz9t8ms2lchvt8XKqNo2OIv+iwlsbjJ08crYR9C0Ekx9FdPu4Y6xD4k7PSHaG4zUQ0uKyqgqvF9kJk82LskB+Sc83eIl8rBNcU7Y1hnrWIkxxiPFMlyiZxGcg2mpkNGiiwp3uSv2Z+z5e/IyyT4V/PlEYHkIMeKjAbCfOv5CiFFz83FgDiTu9ReNlch0N2DQ+vOVNLok+BKskrB+ngJrX/Cwj73RtRiGFKI7yQO8gTH2Y429do6GJ0wXZ5nv8/3/rLcP0jghtD5IUiobWfNw9qvBqKeG0xc0WiC1B91LfaPQoLaKRTJtTAx13qk/5fEseiCwJySH0DfEfLgE/SYoEVMHDf/1Gn+EMC0tm7R1wWTvt4Ic6qz3EWN4Uy8uoO65jHxrzaASLjbMA/nzAOX0Qq0IJPEAkibRyNuCfWLohLiwtOFDDl3ClFgTIx+9d/cDg2LPBT6c+9j8IQ62RQE9KNXeGTrLu661n3/Bk5g6h0IrC1SvhMJiEtPBoWAjP0J0q6G5VFrejLmlETUwV6MomgvtlLyzZ+j92pF6xjYlB8HBbiC1fRIBLS9QlB3hSrCGwfYCcnqcaO3Cv2uU00v3vHi33G1KnwYKI/GEgfzOul0G+tOqKTAX37hirKW9IMQAKwfoSDB6SzuRX46MfGsdJwAIpNLDbO/lxJA2OeMa2ZQrlVf8BRVLgKFyPy3Rq0Y4LyuImESk18e+k+k9YpOSxrOoTAgbQokrYrrGe2GqhRWRlODIvQ8Ttq0hfcrG/wpL56QhRTfEpUM9Ur+NDUJKDZ7dHr45ROsnA2g9Cd8w6sbbX/OgxDVvl6ygJXjWd7TBh4+6Qae4LWA/d6dkVQpAnnjy/6dc0BaN2zozh2PWTHMR7ifWZoQBiERlv+/f3ubsZn5WdSWebUqX8lk254V3uQG7wFbWzuYNmiMmC9AvDgLxtJJzg6CjkVQzZsyxlotVlRq5eHFNwqvnJ0xAsc77RF4sunCxIOq0Jlhxv+9NXFXvU4b222/Mz/UAWr9jlnMyALmYvJ+Ttw9BeRYj0zq6efk31xS344NNbmi4/7VdMNUxLbOmqfJoGjCw3BmFRkYX6xKhkOt0/4H3Hj/d6xHm58XlVDbiv3K4pc90HpIBchURQcdSM/gN1Xqbpywk1hcUH+P5Zs4ZvMbinuMmc5ECLi+0nM2hau7esS7ltsJxFx04DUb9aelRWKbKSHJ1750TRLTtFGNF1y2t8mjF+z/I6tugHXXp+9SWdOzCz3KQkJ7/oHNasyEgVHvkC8NhARXjlrm6xukRLww1a/QWdxKcTF7ZMxOtAEd2Q30gl7GognRywi7Az0thgiZkfpvtBErn9JhO4cEmz9o9mKJOOVAXZ8QFJDa9QmAgIwTjvs4ZpqY4fN002Au1BMRK1xpXLiLZrGI+HsYd3jYouBFUrjnYTnASk5vAwdVWcbnbiC34OjI42w35fue3gJsDfMGJB/Bbe6YIj2xKp4safgK8NSNIaLTKDUg6YbMNgscn4I72ho3mmiE2g8muo8Tp6pU+03LEOna3sSRSttmOV6qeZnqGJlMGY7QxuAeULtR3XJoNBpIG8lBniTXdMxycvSDaxJ/7mCi3OcUKCSRVfi6KoCo1it1cfCxGtEj71qM+bYc1wlAHwi7UBMu2U01G/s1yUxr7O555/GflYhliNVwsNg/EQZyfeOacKW61cZzaGXBgO/mROn9cX3q6p9YJUzZlZ6iFNPUBiY64Ld+KFA2JxvDtKUO4/JP3gWn6X2R5F8aJ0oI3chfqcpLZ8kCgQq6pwyz9xkkxhPrlTKz8oR+1EzKEcqB+2aA4VSxb1CxkhMV9Kpf0x3TsGNmV2zz42QKTwfvRsnC8LeIfBmXcoTKyY/5QFMC0MJMDiVaNGeDHEvfYazGW6/ZySyPjh08oJUV3qgfEQVLv1kljJkyf+nhZAO12PQ3ivthBJicml0MRTptQDFEDu2e/2URvibZn4xwNC9wyWIR35YRVweduBQNkWjNWHdcV8IuYrZc7aaYkZNJfISG+SnPFP16BZSImceseZ6AGB9Ku2ZQbiLUA5t8OJhdgRyb7jD1kzsyQE4kJup/cZlrP6/sqI3UU2PslLMLgPTDGJOZgGeqbqFy2NuOUWXcy8roc/DIpCvWCXx9XpVE8xD7qDAjmZkIzxEKTIMTP3/m5tEAbFfcj7GDnK6vvK2mKd/Hq1S6vrgK435FcKdT/IOvaKLA/vjJFJ6qgE6fSg3TXkFlq9dZlya2S+HSkEMQz+0Mr/G8IAmbsh9f+FBDqkaoSwUg2GBNzxmDCIKgcMF/Vt5+BacJiouE2dSqbBIFXXuyuKqhOHFUoV5ecz6+spoC8soTsq5yUssxQ8nBXTQgI5I9MJV3kAAw58VbE0uv25oPkjGbuNCmRErGlPm9mgFNgdH6szNcuRO5cDQoWdC6ne2c0TfqecN1xN3wU0jgAm34WKF3NiKnHNWKXdrkihwTHQEmZW8F8CkiSIH2BrEKOHF1489+v6owwfzIiTtTqL3/tIfbxhLTXf7k4QtMIirMonxqmxT8gc7b7DGwiw3xO0iFyyhFTOp/ia4UqKX4xf9Lr0n1mIyzLfI1BJi4lKBXSE2agJsSY2u+P69TRIgA5nklKuPZvIG4LWduy6847x6LYoN+zF1R+ZJrEMIZ+UXF551+JYLoYguLfGITqdzq5z7ZpNjKHJXkiVRKhQ7uWPatbH+q17Myp/lSi5mTCnNvLvCiwWwJGOInxK4T3HOMJ9T+ughKoA1Gc+3IpS1NwEPqCF3tYqpvuftocnyojokOerlShpc5/TwWNB2XkHwprgG6ENOPOUO+LFgLh71qXZKIO31y3rPQWsRXb5BlHz2/A5MP48gGkESZer/8cl8YUJiQ75+HSzFyTOv4K9NVWkraqaVCxdmsWSywIW0vK2viZO/Ffiu54SqOtylPJWAqo0LDLOVmDqbeVXCCpoZKvQCx7L5+JXo+ghtwqw1Z5tqGgAWzWQZQtDOCksv3jM2RZHVqn3+wJAjPW3zAvUP7aG9+7Dw5D86ffRwaO5WQiIFh0b/3rCox64aHWAQG03CxQkPz44Hebp5aHkFdSr5MUzXvK9J2rKwi75R4PVHi0rzJ297s2Kko/OhXqSxAo0dEoiWnYfQs/6C4Mmp3tGcdVuhIR7hzLpiyOVW7a/Xsk8JqivuvjWlHqX9YnSfeynWrFy9U02byDbM30vebOc9if9CxiYKBAI9dXi78zUfnmoO+j9Zh3vVSeo8NGzaqPFP9S70tQGStle6h6IFeGWEGRhTL0V860k4aE0dBVcTLt+7fxZh3Oo3oUhvu4ewnDLuXHWm9q5YeXB9WunM7ChD9ToOCLjVhhKMGceyFC3RB/w83FfkgGglyPlF0Sw51SIoZkf86izMGZtJ/8vexv9bgP0xKccuBS+1z7S/eMVvzjCQJP816egc1afwvQRS+hWJQSM07BnoltevbTUAB5K6jC15NLU1WHFaFZnfO9IV3eJI2p3VmwofieBHCYBwXWQBv8kEtCVZY29iBlojSYDcrrWN7DNpVu0oPCPIbXGKHa5q3HB13tWI1USNdxgt9vTKmhoTNjDsrSNVAVaxRJuutddBL3J+9LzIBCUlWGx19+ggRbnGFDyXBPcmO/YWpHxekVfLDKSJpAC7y7oKtRfRQsx6u5l27RnrPFUn+Fgwp9zJpv9dxDrk5krRkmnqj9f7oyxRtA+rBFVBGfJvV2wqXWurrnF4bRYHYCCkeKDz8BU2QBTWCQ9CdG3yOmjbe1jEiNZK5IX4MqFQxgDSjTSdhABNzUUXoGDnwklwx7D9p8SOyxcRdE/+Yr0Kr/IHvmr3pOcHkOoiPySkvkumYgz26sR7IkLNQjF3PZcA3mV6u776gBYqJVURNogfY2QLuo4zClxsIdlqYS6RwIcQB8n92T8WS8NbXyUrGsZdfO4WTj0VRD8qdMxrmfV1lLalCmBEfqM9N3V8nsWa5HPqqq62v1Vte5ck5DDn8Lkwcf7BZMIiyeUStn7i/6J8AH2UoIx6BFXqq9RSm+7iMjxPqfJupt6bLH+jnmlt+dbdHQe7aIYJfOD8shp+I+AMQ3ShFIAUMSGRcHJmqUjMviV/VkZrGtBwuxHcYjTOdQWkDUEDgrizVhzVF/XbZAzRx/et+CzRfkJiUtOrJ9pPCKtoxNrrGAqmJgrhFId4Z2RrMCAmD7WWd9rOe9QhnUvNtMrVSAyWnUb7BmI0WedY8Znt5FdRAB1wYrFodzRBxypCVOJ3sf2xLEZtkhBtjOrUGf8YdnQ5POjE2L2dv/wN3ogZnxZI+uTlnAWT/iqqdVzAusTWY11l0BsjNm7P4mvTpmPhZMgm+SyWQdUOLTyJPDRsKFhsMPA8qMlWIrwaurkSH+q5uZKRc1e33Cklywli7u3Rfix3TzCHsQvvUPXrptKFYM0nAQCXva/+WLkVzIvYG1bY6xj0OZxuxRWn8M5E2IdFtMvydQZt958Q1OkHNhS+oArthGfbHv27dexaDt+SqCKjLtA/om728dGLthd5Z4eCtS0M8Ul3L8yw8l7ZweXTEGKhfc7pZ+QSnwgHnVZod17PwVE3jA6VZVPhT6H0ZuY923doBKhhl/1tOf2ERHmcvxEQnUnVDyRODvds2TykAn21Zs8MAa57yn2bBf00r1IUy01whBW6+xE7FaztLZMe/iueh00i15S0aPnoDaw1BuMI7GHJVIeZGvV1+IXHLrg30L5ZQL6N+/66ue1R+OurjktZ7dEe3c6yThokGT/nxkTlErJ1piUbUKAsulenzxjVR5mSB3e+i8rM0KTba5cgsgPh3YnjEsPg2TzswfGKg56t0mL4Yr2FT2SbYEo30b8cnCvxTFA+7OmIYGZx/+BNiApfzahdtf3RdG2GtMV8tITowJ3Ygng5OyfArD9cmMjvHJ4mVHBEiXuNy8B0AghV0QoLSYIkPw6XbBNKHrClvEdjuuFpQfJz6sVAcwXcpB+BFH/0Rf5SzECzFc4AFRpKkv6vew0V21gr/O2Hlk67rODI67uWM1ori3JmhIDVAOosT9ftKtUkKAzDkd96ZVDiGmLOl1o2k/b2PSXaUOKEiPLvooYepnKJL5BudCS2JSjYyiT/fOrUlP16KHYE/xf+7G3Oq4VwivmkPVkknEEyMnLm0UuO95NnbYQyCXvEvgaQc87g9ti6FemHHIxgAzYa4oMg0fQ1Fms3Cmnp0zQVdG0lc17MZzX7J9bgqKz+687E/baZwQKlU5axittywlG91hrCtvSNIOLBG8OoHV2vUyxmLnVKJl5/tRAgHZe6HqVYh3a3br4RjGHwVpWS/CIMZJGjHx3u/dh0txEKAR3cNwUBerWT2q2LVVNxratL47WqEQLI4daAl2XXLjhdzXYMBhwgBLXU7L8ZlHepVW01koxnKvi7cCRHad1DWa/6OsRFaLfct7koOaeb/J+5ehGsrn6maSR30bgPFnDboxgqCgCMimqVPsU2NZ3KfFKYgogeEUk95FMW5ScrrxCvWKyXrzFZAJNqhcZsD93rie68W+pHooE4rKKX2ZkdGie2KwOG6b99cDP8GfoY96xt4wLOUom3OYAv5SJ8zhvMnlgYdETMVcUBb/iET9iqpCjpIocVgzq3T1d28wpLLLh8hCPjK2w6MACFkFKFyLPlZ/EevVg8GuXxnb786H6J+zIuBbrEHqHC+IjgAqOEISCIMma8srRBsMoWGWrbkry7fjGLl+KO4ixcm3HLuR2e8RXUa+C7uNb+vfJqVakcSND2yKgPh0H2CeyYzOQokckHCHtlhnPsE2yv/JbeYhRov6Nxi10ej0LBSThcWPa7d9knVyTNvNxMwUEYRDWpdq5hyHFbtWDke8SxlZWzCJCzLTEUu8avtfKqVxEGxKS43RxI7/MI7wfE7+g3ZOsT5vkqnOuGYTqPwtL57W1KvowYEwxSg9peIMgH7HxhsM2hO3e8mOdyUtphHWT7V+X8Viq/3SytMOvw6KNPdovA5FbPurT5IYDKOlgDmvecUqNAtR5Ulpoj1QlwYuCDVEPuMkh/jCIbju/rGe/XnCx03X9yI9UF1qatdrkMKggOjcN1U5gwQBuXSmerjELjEYtkQmTfZZadme+bvOY6YWaBENM+gfUvHw+Ssu6hfthCh7Z3CEDFwsmiLdts7+8PyotYQOi6nszTz0VtHKe2hhzibhXRueoRWzd8QgbCBs/i1GUnzMMLBQfNtP+exF5ZzUHDh6rd9mypaoOv0Y41kQvI0bpMdBm9NxRO83O8XhQj2IGQhFARTPTQgyXDsUEvLnKXMguAF6Hk2aOWM6+lW5rX6c5zMM6E2ThChEhCV+zlKC7nLpBx+S0OjjhhDBadE/hTDHuAqZ4zDuk701tV0T8xv0RZ+nbO7WyMddsDuxtpo1P5hxdV0n8CTJaQE0PoINMKu7P+fb6MT2X31L99v5unJXx9xUcp1yUZfbFVbchdnfd/rSAD+amt0uDc9mN0iCRn8RRYBIp54sed4eK/vRUTLxYBVMkZ1/vDj+f+VhEtEhCQ5+6UWP+nVPQG7zw50+lzNGNuK5ikZAWBUX7+nBEBGGo5RjNDK3M4QWeKkhchaqcrHvfBtzR1qth3WGxTxNF0MPSzTFFNoYFv5qkgfAb9BQLbJlQAJQ6O2vybTa5VoyLYB0Mgp1ZX6LYzsDZMe6al8EDVSoquMPIpQFP6SYGN7umCGROTWceBLID1nNeynV7Pe16eiKvRIXP32KXm3CgRCpGq2Xts376o9aIuPJie2B6dE8T/vabWGzHLydgqD7COJCUeOp96/F9lweSz/vNcd4g4zhhcypSQqoRc8OzBOpfDSuMY25iqPVRWDtQwHrHmRk7DuCobikXHIPEtiMRi/S8RVdcmIPQRIJ38qxzYljViwK5E7BNwnBntypslvhspwSMWc2OvMed4U3b/gvxo0bGJxNhHp7qwal8owiKCXfKoWcTcDDb3ruH9MN0WwTOuSvj1mu8ACxt5mJhmGsNoRvdFAGs7ShV8b1WqSSiDC23sLCj7HE8VhxsHXlWT5+vm1Ej4UMnBxdnSqjL8oUUe4C+AqcvUmHkUHdIN35ttMIR7RVgX4sKpTAXUbjXkUR7PrKzLlRx2sTRkIK4iAa+vPyRq8CV69UHjFUIztIQig5sp4GynKTKigJj58Sx+fPt4Us5yJq6bYx/9H871MTfjc5oTp8lytIHqnwTQ12ju60kRfrFrCqEdMbLJTIa7fnWLnWzSyG06B6Zabq8+DCFqT1YwmzWwrp8nxMp1mpGRiwyTf7sjy7jhhhA+NoCEowL6uCmeQOiSORE2kAAuaTIVk15qYkREujFGAAUmJdIdjxcHGcaetepf4op+Rf4LslXVGWtKUdV/tuh/RPi/aBD6srybQRCWv+/TcLCFWkl82bztc4+gyMCEoMSyWOv/6Q2J8XCPtldbZG2L/hbQkSM7UDjsi+dlHFOsIMAPg6FzFr/Lwb3g+5uts6c0lavfdNuEmnaSwDSiPhBDJqwfLRvR29QkDfazf5/VAhZi0y3McivVnMALB8pfvByd5VOj7WzC50QKT50nNe3Cy692GvZOILOOjbWYdgG1juWJXUN/gSmd53xCCO/sMph7K5G1w2MHVNyaDM316SBbld1Xgv6lf82iykUA+LI+69UrDvRRL2A/xwDNYvW1417abuwSQFo4wOVlR3la5ND1D2ADhiaxkoJANzXWvOpArBMtIKp/XaDRpS0fy4Qnq1WXVXYzo4MA1A4claedAJi/fr7Y+VprEWryLRtJqDn8np+MyMCQNwy1G5VIRYTmcO7YymIGKObZ7Z8tARfgp/RhTjneVKJPMDyXzbua6eg+LC6ycsAuaVtUI2SAFx0Q6iujj5x15Izj34l73S8H7Hs2X8Kvd/YnQ/EqM0KGjsA1R5Lecy8kGDaYKdtrRupoAAffqU8cbjhBfLLekKZ3FPMwaX9Bg7JQSOHfSvXor1u56/zRFqxAmABelONkyQQDkSnqhp1nUFvS4b7x7CFld9RCMtGlMNka9AO5VSLDu2zK8ztAhNHTjKjB++efuX91GXCc9AyG+wmPVXsrfS3QW83FW7istKcAFm3ZB73Gu5gsYHFT278OrmHoNZZCVkzfYJFn0rTOogzxwX+pKeBz+KK6z2KJkKEoj7THymciHTDuByLC14WJ5ZFt9+MGJ/U6xIRUJukn4pMyu+/Lnu8iWP2hr+SkuTKcGvYAQnz+RTfXDSxr8rQjw7zrEQyoBVVjVRFePu9J+8TkoUooOHWeXDNyiEO6eOmYusgr2raMjD1f07vN/zwQfMkF7MFJ3QCwoKKHFwwXrzz6nNFLAoWy5QCwQyYiLH+xPVj6P2uuZ+evSz164yTSKsLMcZ2yxi0bD3x32PPZ7mTM/L289VLpN/tirwMfr/H51uCxt7osrg4HhssoSraZFi+4X9TSsVTPJANFPiXj972pHs5M/4q8B2Cht2EzvbBKwpSv2HleQobo5OrpBCsmsDSiVambRLY13Va3UBuOlkFmaxogSVBXQJTX0Fpazsg5IfbLw79NX9DPhatycas4EJK7OFGq7eQ9pnwNeqFgzN1wdx+UyhQ7DfKlQYqpNSmjAjAley5leuYf4SyNCi/I7Qj2ufZJj+9R5Q3u830ka2X+ZwxD/vDQklTVJc6JwmwPYjCvVxXPG7txf6PRk68deLE1EakmqkD0LA7eGq4XlakofDZVosH0wATQY7wt/aJv0o0hkkHA2m4z5UmyUWGZkLT6VLCtTGDnurq0LijSLuZK9DAvKVZvYh0SSm4I6Kpp/yDmNHCQHNhYYtfKwCKri3QFjA97sGbkdvz67RrgK4gWhWyAvqJQAVlNAQZ4Es9E78l67oucvqy5hP/PmSViJkWMatCNUGrPM8G1oCS9HWlsKxDaoHIZyw8Jv9Tpg78Kcw45H5zxqhNSojfK3LHPXWFao2Z2lxfZM3bEUeVC+XARMdG3wpSBdt4xx96+YArOAqSdbCV55eUEMdsUyH9Wnmxx2HG20miUdAeJR/1mIXyXxN4YWxYcGxSXG9j4eoQAtFkl1+YKgNCRbwl/tdJgqSctUDe9svPol0+JUud/wCtmhysSVvCvl1i2lyyPor0Yagw0rEaq3oHEQRiOKDqeAmDYfmtMYRMfoDN/+60Bsn71JJRfOVd08pjYIyFDZHzLM1cujQLMORc8VCKZCzHymE6l4l/nq1puxGMeFQJMx/z8yZxU/k6w2wtbyFPwfcBI1FskdwVA6PgqYlP1nWn+JLWUDvl1NBv69WYOR3/37jULjzQrw+r+wL6ZRUDzdurdNNuMGJgatVJAnBXvB6lunPGZnq3oVCguqCVkg/kjbv4IoRs3pNycST2IHzwCNf5EfOp9/hHGLO6rCeUctroYmjDO8ZHrRKM67MovAifuxW++X6qMk7rsATZr7QAyJ6R1fpry+xLnySrwo3fQx8xtssLpGOYV4jPnerkcZlJXMBFCd0wLSfMscT/HE8nvk0ZiNyQwYzsbLoATMHoo9H67F1VjLoaL15pw1Y4m4Pn+8vGc0Z/JRGiStuu7mcvHMG0sax8L7aLMcfUAYwcNcIT5cifBiM9fw3Y0omVsNoDkEkg8BX7EUu6LMp/KHpitIK33TUrHH3amGyjaY4N4PaUKNw1S1TuP6VjG3BABi0NoC3DVFJFcd8z1hL68dFkzIfhBEFkGYucpXavSUjs2OUgqV8GGiRtRiBiznQvQcqeJip8XEoT1lm/pBvmikQjlcoZBqCa8+0CfWBISavF1LJhvKyKub4ExU5Le1KXBiG008yS/0jAHibdUUfppz8cWIZuULDJO+H4pAKwWsWLnPWi7E21AAVnNYYmyXJIYhE06wP/5L1Eny5gDE02GLh8mHupHg2B0tZYkAPLvM8E9PrdxMccPW/TNdTgozHY66pASmfpzfGH8KcUXRvfihWweA9P0qgGpe+i9zeoPO3v1EOzwT2cGWuQn7sf7x1d0KipAp9GQj4woxojTHUxsO5KxpDh5gYZndl564vBm1Cb7V4OYYyYSWLxR4ggtsi89Ucao3M24ddY/7+5LS/nGpVu8RmT+VY4U4DNP+FwxvJtDUgj1eAvfe2QcY8d4/j0A3XDzL4EzykrHJ390GOKtSyUyfWrZbVlEjHGnnjGJ4FlmIvgMkHHGksQi9hC/iQCbpSbwFnhiqePmjHDkdz/fJ2ASj+NjHYLcTG40kJXA4Qrg1x8CTBu5yJYtf4arvE5AhPT9Sym3NCihrPs/eIXprjympXRLyaNHF4sHMKxjkJ7LsH0jY/HmgwLqSGWbzeZtP6llMosU5w0/dAjvMv5gWHbDwP2aysuwhwRTKisrAFAAEII0MsTV71rGmXw8IrWEJi2HagNHj4EXsh4jkX+1R16FoJm9MO6WaeqxsTf24b9sYlU8bMM/dBT1kgEKh16L/2fu9QAFwAJ5AJMshgVXUpqwMFKKrbP6+06nYObk9TXj8ug8ZiDl3hTGAlfOS4KNZIJEvzaJWqwxnadkzNsyHiztJq2ywzIW15QUnfBaGpNRJ1+ERJKvbWARLvq/QMEBu4FZrhf16/ag9tsTfSwc1fixyujiAVHJrSfnjpgIpLN8BHVXVKezf5CCyzl/fvK2BHg0GuP5Dto2Sc4sic2gfTnF5iUf/HDEBOKhDCqo7J6GOZfjZEKyJsEZL19pW7X5HLdKsZdo3skpzxbnfBsW4gR0pDXlahn+iUm2ehEgfqzJYib8zDAE2aBNShQN8xPxNKL3sMrRsb+MgbJaMZ94PuDozEWfr6qWQXPMNZmHa22M2HGxpUYONip4iNojHqzXyu7HGvWd0pbYUpkmcm6jwT0XL0aBmcqmSCsDrZaaUbASS8SOixTljg6uhLChubFf3mB6wq6irKn0D2jyE+UWa8BYFtk7xYW3+9ucbF3KBNjf88SnxcGBW3lXe3n+W77k37huTcA7z4cUwdvtefCDDHvkdXDwq9zogmdZ+Yp3bZMwKIhc5fG7NrDyhPiMWfabT2HldLmVi61zYpv1pd4rg6CKVa6qfGqOXOI62SrbM/V5reo1piIwqaXFogcediEABQtsMOwqwhw7Qhu6PlgQgtI6vlpFuktEFQdt3wQb+dVu6lMgJ2Q2uGZwxIGeF9l9eL/ZltEhCxsFC7Jf62tVQ+TBMfARY1cMjzqLLQpo1P5+OuQpSt8/bil6kMkrTMM9tCwDb7ywQPfyvnOhSXLLpBifHQ5/5EJKjOhicXm5OcukQKhvTw6ZzZJBUbBZ+cVhsrnVs4uFtQWmTH4EVPg9bRQ0S7EtwTP5lqHDvLI3wkuFqOZTPorLzpxWqmRvYM649oFh8nW8zcl0jR8kLTO0STYGti7TShdklvf88qaLgLCRDxHwEfYzQNQpcgpM4L4A7bpmBhk+E+1FT6q6M+/pWTRxj6Nt4BaTZ3dkDpUbVO9U8TuH5Gay6AiYSeuCEm0qaZnoajefkG978LNBln/yaw88y1hAay3cYWhk9tIw4RxfpXmMA5yY+Cwb6PNvPWZDo69gzyyGVPL83mtMtHuqoCWfWdRtMK23K2uyLVN2loOuPwyBitkWB9bQiqTmVX1P2qJRU+ILnhLQ34YGbJpZ/sE8RZm1SG57IMRD99cAdJvsKKUPCczG9121HBWlZ2gAxJPEL7yGlJWhGhPc34cQMpj0Cqc0R0x+mXAD7rOcSSVL4CXxpfaRegflp/fA42wepuBhFCo/SU+CdDbkJ11cF1884V3h6fJbdx3c663wIcfGjSJxHAlhlL0Vgc/Yqq9SNyLave5B+eOQBu9oTLqXzw+FaJ/FiDX0NWogQo6x7FLgX5VtUSWXz8eATB6rwBdp4YdukBTgwJ3viBU4gmDSfImebkwnu5KULO+SPWdduVOuM9F6R+yAeddnkGKHmF5AX5eNuYodNRWN4kpe/pNj3gQgsr8UDT/tWzAIKxGOlcJ0NI4CtFhc95zFhq+B7zp6dH8QazX4b3R+We08iGX8sHt9jS05yFzWJZitKU7/8uRKoaJKz8iimCvqnc67nL6TJFUL5c76p4ri+i+1jp0uMWsP7gOUnUE0i7gg8tNGQwhhtjgDr4xSMCAAopb9dQ6Rl/meAPZ8Bj6qFvOQa4m7kfnkaN/LdFKiETHVpYQHXvB5yQh6AP7LYP+KzflNWohNXgvmz4hfYu/leH5W+ZH3IBpRSSoBSaxGYAqHoZxV6KGhzYUM2bkuNmsHRflM2F/cZpR5hN9FStipTQAcm+QIuSNs+eAyrpRoIMnmswAO6z+R/xHAOUCD6/kO98WE/ry5mxmEO5GdERZPSN8tIqnGMoIeAy84B/ZWCiTLsd007Q90aT+XS7HiGf/83LOJzcTg1xEc+bEV5KwSxyv4Izh1HRWnUGHXAc9Mo0q9CdL5KiPlNkMGJeW8sRB0iMU+jj0a/RtUC7UaAzaOjLGGJh+a3IQXHOhAxXjunzi2J7t/7T+BJZW4x/VWEn8OpZ31kLe5ZQH+oFXAhQliSc/Kp8ctld3lFuhf7Ph3FXoVtd2+rq50EZRvnkYdhVeIc32Wx8WPcmq2Us7BpaHGvrcuOXEvo8Blf8oWD1Js749igbcLYdq8pQATTKdRqq5hCmpbPjbGtKsHpHsDJ4ikpWG5How0bXepXy0GDnCPaxN9pUHKLqHFrVBJxwpuyz9SkIdKPNmXkMRk+YdZ8/3MZerfm5UheWS1NnXLjdlgE7o9BHhxUnLRxbX3jWaY/hB2XuPwbZqREAgDeBRA/Gh+lIdn2t34zOnaZ1Vphs1TqAHJC+fG/Hss9fCfp1PWEYV7r7GZZL6/cJd3oJg/8hp3gYE46udI5dTrTrg15Nh8IDIFke+t+s2LKrT3Ce7SRUZIlMKxVV2JsWHI077HKbs7dQOD0dobrRSr56uHIE/wUqfR8uyDUJfPty55IkynbvU0zbC5u+eGI5IHc2lIqijwbunjlG/IKdGUE6jEAVzLtgiFWgO1klqk28b/NUF7QzPxwFFubj/QYG2WzE5c5mz1Uh37Vec2/wwd9x0LL0g6QlJG/4uGrWjIcOBbpB/nPInz4Q3j6CSYbTfZrdf/CE5e9bOXKnv1VbViOZOcj/3UPIH4lQSWj2KfN0bRKJgE9J6KKUJ549RWB6THWloSyBowngz9jDK5w4WKWp7IfmxWjERq3M1qwCeD2g8z2eDBeaf1WyuS9u6gTFxnTirWfmQMP3SXBtc+JBYF9Tmz/A8ev32MTRvFBZh4D1uNVUWzc2NObMmlpZnrGZhH5t5YgZ2qfPauz4TesL6FtI9ngOHNkZP/gijK3pJQ24mRZyZHTw3SR68yU0bnP6w+U1E1vZfeaEW+PUz3wlyjkbg0OZq19fwF+HMkUQYm2Z8v5L60avaY/l0Tj/ghd2JaZfMOgdf449yJL//bvOykKybx5YbO0WCmDM5Dfz0pThsXbbSBXO6vNcSCYsdwwLgD+bxOU3cHdDyXzfN1OwPvB8fDOba9Q6+w4mF9RzfqL+611zTexQKN4VRDdkVOedPa9mdJUjVOlmIzV6/HUqg2Oilo3uBa4gfRpL5ApGqiJtPSj9rXjkL08P8Kznnln22mEmdjAgIrFvmn7IiIU7aAxH6HfSxhnQQKtFGdqGH4pPsRUl2udIbbigZUXJlmOdJn6QjhkwBK9LIYN5333a/aXGd+C/DVa2Lp/uWWOZmCXAw2HFub3Akj6xPpcYzpyhIcgqXJ5yityCzs6jmn79qOY8ynHxnCg90HWHf6ZtZx5sAWHXUD8qtVOv5RC/OkTRXtM/+a1lg5HNJO8KSYYke1x09+3l4dWc1u/ItaPZKNc+MJ1PNl9sdEMUhXghAhbWpbz5wn2mFE35FwdvZZyQ2D/W5RzyQ9foZBE4B3CJqBx5UxAyp6+x27HP7gm7eh1tbJSXCVxjsYRENUJPX/E+I0sSU+93jbXtXhzV6QErj3fXj651z/SdfP4COQzsjlY0dfTdduelGWFCnIf2IQ0h6Kuxtn91h4WAShnuJsu+XWLJYP+jdeO5MXHp/CEO6ni8I2UxHJE3+72fg3jIo1tuqcRuDIHGRDqIePPjUoLhRUN8BBG9ChdlUOYCzqDXcBF63Oa1FtPQmDz6+HzM8uhACImxylWoU67P7y3GYOsu4I/BgJ/5EDaoMtZjXLsulWJbobwxnVnp13b1V49HcRh+58ZQB2t3P727nUlx7FZG1j5ooU+unRnHOARcu98mIil3TPldL6738YQolDmuSLXpRQIcUsSjaXIsavJEE6Q3Q6gveP4DKrdrg6dXEQTUfSL9d5Lzqx9BGEjK+0aNuy3xmnzAstddtLTmxL38WrEK4wiVp+HiloYQJvhsSCFVuE7V65p+0mCtutQx8n/lO58RkhEwIijGrvZv+wo0hcpOMlAl2wbcjwjnLxr1Qn7na9znwIyDufIH58NbnAVWGUcrQLPqIrEKEP6ksQur4YukjRrMIWGdrf7EJuj/DMWjVvJwxZQeyfMPuR3i8xxA3eVXy93kbnEK4nMwndx0S8MAToGzCHh5ZxT+GLB2NPSt4O9cg6C1ip9exL6FXHh4ZJqxNCqggIGA6FoH+r126Zawl7OSOCkqX/70/UOKzFTDySn0NGDfP5/qneBA3JVX6VNzjZDeTulPqqC4kTH4rbB2vcjHXe9/LwL+F2ndh/yoix/Ouqcf8mjhZsxkwp7Wu0dnSSNeeV5why1OTVePbUX8vlq3ba3RAcrsY26mNaeqiwg3CrJVajkzejZOO+AtH7MImobGTisnA5TcidjSC37y7g4RfzqF0OjAgP3PbvH5XMHpc9r3N8QpMhqM1Dm7MZ/O9IZ1IjpC8ypez1/OnSDAAxuF+SOYbndhIm0kyC33alODE2XLe7SBkdwSgCvJyLFHiFMJdb/LAb0/D1rlxi3rtWSHsPTGnjr7q0wDvl+AwM9GdWQwtgzusSGNeRojwKmuutxGeFKsyyAmKbWYOiiMAeth6SGQap1t82UqFK2ASkuXe4xXmcHo9mX2bjp4bt0IbVn8zuNLjv19LS6JWSrueqpIIjR9nEoUuv7QncPr2Q6OVrZRjlrvYo4P0u53AI2YMJhssqqBgtImPYVoZKK+oauR8+q5dZluAhFJowhl7rOq1KCZDOeMwtRnXzAsBTAx7+iwA92tP57rBqoQAdclte3rJa+bX3048Ev7aN2jNebmSE1IS0EVyddOinlUP2169ImZIdji9C+IsK8a01tg+P3QDNaH7ejCDQi0fpwEkSTfwPzBJbRLRqZLYMmfc9iu6HZqrlFUe/28hu3XoqiRXYjirOGXKon4FDiUzwNiA24D/fiIei10JXK3KcteloqJ+3lnOnQlPtV4qv4VQatvuGw2rAGawxk4aWncM5mJn/XRbo+frWTdrqer3xdpSOAECQGr0NqQJrf4R9O28Yzibps/Cqy+DZmlBtomrq43rdg7IMj/LoA+OzHcPHrvp4f1tpx79q3nQyI2cH/kpVaXzyBpChcMoLBRKCTI23EsaDQwm9glzmF1KmOHZICjngFLz5zB4bpep3G5Df/M7N9YNiXHAsd5FMPM1sBgKCV3+1hdbeWGRcBA1CbT56d3FIVMlnIlx5Z0+r2J2DjydCDLWlnYjK3pRHl6BgYVm7FLahN0hjeU036JeFWMy1H3FShlobLS14oSOJCCbcKIOA8e97Cs2kBY7lq9dECs10kittXkEeOciuoHNxY3QCKMuXdfVp++cMnICwtKFs6w9TIZt8BFgMPdy5F2wG2bpI5TKRTd/cqF80cNa1M9mqxKYZzFSmoW2r03zsoQ8ZFzj7kBPqtjmYaSc3AoU9J9qARiiVyLJBKJEkhAF8XqxDWyfsTzqtmVGHBqzgrGNJ3phYb5zJhfZeLCFaReLuUEq4Hwk3CKAtowi8pP1RywSpF5usACXYNX4LKo6rgrB9Sd6xx7Qq46Nl9sCfYBLQ89eZRSyN6IEHtvSpZe1RAVN8YwH+Ob9ylywSUrW/BcEpQHiw9kEj//iEy9P+4Rt8BENE77gUl+DONX5FqL9DFnk6EoTxT6cUYpLx5+/JAXAmJ8brDylK1ya2zUksE4UhwiK/bA4Qsc3OGILKHVljNQE9kjGGsVfVx3gZjRTuVsiolTAwlpIXxLfFAT9CYrz7vyJVB9j32gwxzhTI6Hx2w7D1LOouPn8oLRWnCjSq1dJAdAxuHmn3njxgOfrT8ep+LA+oJeX4NzjD0oq8jLWuGyokbMpbvTlEIqMBNUS1NDIx6is3w3DqdhZ+yPsSgfR0UEdd+y6aYsIuyEjbgW0+n/2eJLfUggLTIi4U7Rmik+9X0kWuzT9Szvmw7xQ52jUwPFzCfdpPeb+rP+K8PgIAFEhiviBOye8hv4hBdxa6kOl0DcyzVUmyyxdzW1uezEDLkbsn0XR2L3ouhkZ90FH1ecv8ez4dVq8aHlTE3tEYObR6dT2jZi2K8djs0BIUhaE2A3XpkYQpuWXLKTFqRa+rbH6Q4wiK7JDeckayqHPkMpg8U2VNCjG8pAZIYB2+bZgd2t7e/SqQrUktqO3+B8S36GveuW8O8XfaQmYmdCt6u3KekHLR/1dCV+gVH0ZoVL0BkjtJtinoNLUhVAFh7iXhdFRXMTpCKrYZEKCtdVe7a9lYGBaNohLRfDO2e3EEJ5YBnTam0AMZlwDvlTwV3vQJwUZb142yZD6yFvxYgyVQvZDGMfErKyw66wfRqCj5wDcGDMYx3OREugDwdItAnkorP2dMUIl9xLp0tUtnUau/n5gJiq9jh4qjsfQgm9v2NXjBg/+bw2m7HXBfwaF+IOSM2UIAnflP1IY4fwagn49DWb5U4oOLw380PWy75HE3m1arXQS01D/192PNcanVqDUFVKoV7rCu7N1G8pMFqF4XWOPYLQ2zMB3S4jz03DxMLVOy6HYZet90TaSex7F4dl/fxDEbCeK0jHgoKMyczMHPTywtJ8tzb4H3ODOaFDEL67mYT8pjX7DkbjxPZDspC/9ZhEKm3QPH0fbz/M9APum0T4H7N08EEHoljjboW7NwWIj9uw3PJUB07Xh+AvZvuMtsJxjmSNGCjWsZO+rBBd/VoGlPwS7ji0cUmVKSaqx0Jn6r133APWHC9Hs+J7iQBvSL77fuIwUtrjr9eaIGl5hq1Di1+UTlNX3VjPl0M8AHdx4kDGtEOny8tzBrDhZsQsP+1u4btbW42vWtEVzlg7pTaWDJffdal7HgiXsBIOl0z9vMBy1qj+qR+w2SneCElP8VkGO4KdMFFj/L+H9UwhQtt6UIfddy3HCr6tEL52tKotqYVebQ4XqoaJMQea8UiYF5c3EsHKdJOYLeQ8xvsKA7koTVTBrz5OUxHFsSt0B+j2Rae8cf/8plDBDU1hAjYNXQ8dY5HpHrz7oNNK3vHQ2fV6wxsYjOjwhJURp3GMPdR6c+folAjZfnrhuHN4wBRP+AvPO7b7mvDhIKHTJWD5+ilNHYWCAov1Kx3p1ytXmo0lVIYpYJ6NWLR3AMT3GZYTRvVwq/4RGVDiQfdc3KqyFTTQhKNLtkpwQGtH+Pu6zaWvRZGz/mt2FUxci1pkfgM2DHBUJztHWrgRqt2ZDfisqTVruut9pSS2LdqJ3raRKueovBgAfWUbceP/QIFNeyeEwOP3bP1UOO1AP3e6oknXJtAp84shgz/P7nxe+OafxKWMpDAXQKVgqzKbKxPb3oNXrPSjmjEnSvYKzbRr2d/JLeJBxLaqQpSsjMvt+HvyRzY23ywiiaLkgWfWGwcDd/4x06I1HkT3Epl/IXrZOfN2QHR39RjyRUmRoTRGjjA14PB/aY9c4xigCBHiHvJNGPRdfoacpM73RtJBjkzDIHvlHAcRfXShFZKZcW7+MEiRIjMr6vOZTBwBuQPl4HA/x+Abv8J6cYMpmgU//RsL3gCAorGAmrbxCPabjv8VVSnEqQcQPgZTFdkk9qxiytqAZe1sMZPr/cxDZA97IyHunu6b8dRQcBx5Ka47MXJQRhiEhyGWTy8hzXp3oqGw7ARw3Yls8snrg+afHXP5SeleEu2Ve/AEOVJkh9dU+GSwGTwwZ9PMpkniJvGHgBmfBAOp0vTtifQj4W07JkKg3NonijrbU8ZVLdGC/sw0gWybgbU1DozZXEtLwlxjOsTIQQb+fRcqy8cYZOBkWxtA03bu41C+uoR2syNlFcPmSPI6IeoJW9ODgvB691qmI0Y4x7DAnZfcmG47dCV9XSCoxdDx9DSLhzmVTWdvXZj4+83xwaHx8/BgWwEaCfO2YIJQylHbMf1mN7JW4i2ypsY2qGerd3fzqiQy3FCPgpzXa7RYTqcje7IsNHGPQqeK7nQuza1gLFzJhtttPrZVE92gHIrRpmi1LYWsWcF0aucDZ5+7WmvHUcF05tBqphKGuNn2mTBi0ObZxR/LOu8VEAt1Z52xgXLfT+nUtWti1K0m9Bbo3bBqY0aVgySQHxaNhmMlqVzJAVxv7HtyatvIvUh9elrwtTY/btQAbDNhWQ/C+Ys8c4lJzRZ/Xi7j5CVRMZWpviaeMjubH+gfbl8W8I4Orp+SELbDABbVAOJ4L67hS7ljSTNBDtrC+NI0idEc2x7rVkYHcP+o9vriHNZKc1H6zKAAuqSHoQbQNBqLXGDR+CFm+JPeD2W3DBEZEm2zkGuOXoFSLTUWxvNlRa+ky4vz2cuzZZJM0tfYFvymmYEpuHHeUszfD8ly8R/5XNrWxNwSmydGy2Ow0q11FgyxqN7uc0Du2xJvGze8AX9ipQkUM3LYT8qajFpsyNPk9mTx4XPxSQLawQJ6YHi8WvzH7SQhdUat0gdFVXTX/0mK2b6GHE4kaYq4IrQ3l2OXxklKzqe6GxWYiRlsRMyDqTzLxX7jxQ3Sgy14WMHyN0AWnxE4Ci/98VftxIndpzD7cXn9S66xexLhJ+3EK0Uk+7Vsd40KQa7knFTW0NwkyneEQWS822pJU+uLfm35vGXSQkT+o4wiUIche9qrev5zWB2v6xrxTF9L2NXvwvQ/pETCxXr6Rq9yN7UOs298AKnTsCkynFhNLP97ZecgyoPwKUTbRhFK1iB9PNwZA7HZil6K5buJOesgl2IeJ/OmubCmLdBbwoNPBAZy6EK92iRiOjp0IyRHDYtrf2LsnpdMrk+CjNl74c0wx4fY8RgJgzN9l3/37VqLXNkH8Udv7VgAV+0h9EVcplZQCid4/OKZAKOR5Ri6MhZuciM08bEcXCjdcIJDxwsQftT+oTD7UOdtc5xBjq/V9EGfLWf6yPIKYNKeKnJwwZFUxYWY2n+6tOpqQNKHNY4DuVXiWUBBLI6S+hYFtMLlAOhk/SX6MZUYGtSb5eOOizzncXE1rNUE216f110r+asy828N5n7yT4aiHG+XPelvu2LG38U1D3He3c1xAuFRat3TTr/AB0itEjC/S6uV1ar9Vrm0fvreSTPkhqgRH5Cc3Uw32eVciS27ps/DGmshHEDdqEM594END18AVn9eVGzeFqkeASSiPEl0GCelkhKViES3IIGUPXo9uQaTeFYWM0oODkcEJ/8Qy0CDZfKOvlLeLcqHiHeAMzsJjcXBGcSAzeZubdbHEmBh6zbhLaePc6nTkbgRl+VGaBnVtEPnTJAuLXzfzQOfaY5eytvfBoTFnuf9he7RsNclfDkOETsbGNxwBVjWVP2fPShMuPjbZE+jOTBMmwaSa2pUFCeeZdRig00aHlgEDzG1tgvQzLG2eYHMcb22q8TWgsE68gF2KRGvyka6kAJpfiBDakxhAfCDfHVV/6eUUDvay9db6tY0GaVmeNoC1GWGrd9a+JhLtie/gPA+5gsh7dO9PM1dughHjEgULQ6/6anrhfIf1v2UAvTMKkq6m2+nsq8+is8DgAZQpMNmm73/FXJQhe3/k0NZiJmb/CBsHGy9gVU6AppHqTloYdXzGBXDWE0yUWdDB3G+3U+zQk8SWzI1Ys4tVw5rz5yT+I47k4NuFfybitJOUumKimgQKILb65S29sZuYfiTg6ztijptx1ED6BhHIqPPEEZgJ/1DR7RYK4utDGQ/gvAXomzlf4+aEy5vMQFyRKVrUBz+CYVnwBHZYQEFvpgh3Shvq37DZSjTb2Kq9UExcfqWuD7W51lW3LYbSTMjV4xqGjlciPP9855iOQY+tElTEkhyYQbSBsCjlb3xxmPcIsErkveVoT1ngr6SqgPHrj6kSUzUG5BnhcNbt34x3dvCol+cyxzIJVj574awOHBaJbmGgrWjDjyWvDlHO6AixYbi8pauZBx4tVGQBRQWzyh89UOPY3Ov0bHcXWLGSJd/coGRhV2+zX8KL6j0c3/lStyDGp72VbZEvcBqKFgVldulL5EBgG1pexTcb+a0x3ha6BIw6biIZVnSd12yLl5PiNW4ga3UzBpCWj+JXZP+rZzAhmEXeVn8EMwlLwLpfYwD30aBbfAMhqpGaWcd0kNooTNaxJ2tGeDjcS5PrDOQYsJr20wZJYO2IvrqqOF3MfIToiZSYrH5BNT9t72uUnoLP1Cax5O0ggmWIvCHsNm4zJ988f9Ga/mRPMd7aFaZQCnGBQ8JlV3c1FEAZH7mEgGUHem2+rwLY543V0Qr+I4slBlM4k/Nqb0ELyi1HCqo4NnXttjl11KQ0LmAs7Q52HJeuakCo4+kkF+xOhV+3R9EeMoDH1S/YB7MgD9YsOuMrWJAylFOuGQ59CqH2aEzgX0OY7j3fKvHW76nOXfKqTQYkDM3Jql9Yb97irQIWOVJDEjVzFJ7cWo/QSXcW2eWBVPyHwIomhiyeWn3koPngLOlY2ZhJJ5JKDJ72nyFKMh1ZkmjYO3oj25uE1vOtGfKuKbsXjri5ms32SP/NKPDBmjqkpQpMxpc0jrM2orLwULuSuZ+heCENzGyaVTkzX7cMcfSq4NaiAomVnOUFf5Zb+ik20lS2foAoEhEcJH/FCCjYqXj24ktRxc+wAc2BZbaxIOgB1G7Eq4Jt24NOgL9oJLAectyCkcJpLaQb1sjdEPKpgmYVOpYIasHgivb8hzoUnGYgppM/WPwty0PONuJEiu3L/ltFDpnd2u3f5cMF736hUO3u7kwEdA8A1MGFHKdLI3u+pTVjeuNimJfsioMjDgs4wh+hOZpoWJj2viaE5GCmVWYBTadQaT6HTRQUYsnNMy9gSOz4o18Kcde0AUdUmkLR0NaNwq2YUVizo91AEa8D+zDh5pEgfIzHChNe1abmA+K7uEBWDfYRUrff13DSsemjVBLinJnPL44IPGbHdJcoSr3pA1D2/ad/5U0dxoYcu0nU4aUI8QaqOoSUHKTVj1ug9LjqP3ptUssr83XF29mv20LUtKu82fL21//4wZTFj8Pf9cj4MCCwfabA+ipGmpzkol+/7BtbOsTFpsBmU2Gr4z4TUt0tF7Eb8ubrvrbT5eQij4Zc5B3AazJ2ZJSUwIjD/pmhGWxQdtU70x3xGp9bh8hRJMMjkfANa4x4pvFTTDJc7/+b7tSDeQ9XCHuzvu3GQ5PcOi04dN1Q5J/tFV3LIP4SCg3fq8sSg54JnJz1BeFnBn98Nel4/vlIwGz974k/Kme4Nq4riEiOuWjhST89j7ymwJJBGkBJ6D6qKdagVjC559D+a+sbRMoDdyyl2GYrpweZR7NI1XJE+iv7IVz5BFZsTWi1e6k3rxfUlzik1SWrFQbEW3SnFUAxwIWfS0pCtHeE7CtJ/tGHbSYyiO9clysgt/u3AN34uLBynrN3HOTWAlnNIRAWVR6l9oYrLQnCUmOdlkTgDrhU5bZsiEkOkt4+IUTm5cKtgkVN13/IFkREILwzrW5VWj4Nzg6qm5a3/lGba0mNlErf96lR2aAEvewVddZiW8Nf/GIFoOuQoRldhGnnL4JDuTqX7abe9RAFeyPtNm9rKfnSuUxrT7X6PpVub69UddGoHtsj3Bn4hpjyW35ZdyE4qLxuQYf0ocxwtSIeNPfaRDBfc9fu/b8vr3KnjgLuKNX48nR0g464xD0kf/egrpt39A0Sg5sqpcrdETP9eUnFlo1yW/xLJYbk2HgXvBtrNF+Ef+pFFcK7dMns22F+PIrCn0ghrYOk9V7QOget4VGbM2H0UtS6KvSrvuEqCfiMVi5RCazfMdgobWxcSveimsc0uWOcw50NA1kLYKhoiV/5pohYpPjHV5Uy8JxBEpGSdMp7ozcUpKowPghiADp3Z1RX4841/WA8abLbmv1vqDXqxiYQbbgbSqrO3ZMB/kq+zsvelVumPhmS+hiapPYXW+9sduqj49ZvubeftGFr1mH4KJ9VnDf2QMk55aesQ2eqjQdmbd+qlCSI+KAGY4eWHpcEilYq4dBmd/DBjNUkHEmER7W9BS/ORK/N9horM3B0+YbxpS0x/2CCeHQEvKbkUwzJQHNygW3UQAWX8qkABQMnLgJNX/GjMKrNTnbioXeCw1wT5Css1LgBmfanYCEwgIfcHly2us88L0V9YVLt5vv0ILchw96fHcoU0XPc+e9ugKeabbrsWv7q8rtVyNlBgUkQ2MAOKZ6YpeHgecW8mVAz1SgYQQUz6kxsBSH+w7wIJXKJR/mSfA6Qqyl3fJeZKiEpG/8SEMPg6+5rcmwPqQYfzWNggElcjb5VaYMfiLwvTMz5kJvEhDiV22b1j9GbcRvg8jAI96NT7965YiW7vMOb7C3BjcdiZ5oN99dYeIyddSVcgCG7mVoMGPxlQUx6wzddREhAO2cuLfM5Y6F9pkZ+J0ZtC4xZWeAQAmJ5Kq3CG80OAKZIEGpRgOlldaWk8s1WNdALU11UXNG/i/X3BD7FK/7fzFqN6fD7Frx80oxkSBrPGEBrOtKk0aHfYLawydt0akUWSKdNE+nP6kbT7uKI8D2U1n4KDvjQgO8DbWh2n33U++4glMFxsXB+N8XFJmpNMhcvOBVEork49cqjhN/pLwlDYOoH8k9fOKvy/AZCCsIVvLMmfn9HnvyqsUemCkNnfOoU5+yZSZR1je9oDOAp37M6p+558q4KPAyXciKYr4gmonaouQ+mSXAPtVdwqF5JBDkCK8nNtZULmbTmQ9fqmnsPGYm+xUm3hPUodzz7VgrOSjY2khQ8iZzZlxX69NLZkhfmDlr/GUu5l360WLlAx/Yj8sVRNBtO6KWarA/EIw+yJSQFpZVv+GHU3ZcMP9zj1slWtuUTtJ8Zj8jWBW7Us0T/OusR7xVnAyjHXitBAchIq1Fx6+HndZDBkjH7Z5KYEPEm8+iLxI4W5aliokTHxxcLgs3/bCmyvi3DF1+2YiBRmKjUgv6Cy2oX5G8JS+mxQt2OIhwgIVmGAWOxyl57FnCwoyDsUwdPoxKviD1PIpindSxH3cCWlvpiPPGCOKzJ+D0g5Y9dCSQVQPyuijuHG4HqG0fJHOlO9P0SlzxXe7jWYhGDWdu5lkFeflsSDl/mb2+PvTduaKo6x0+Ocu6KTSWQwAkswAZG7llmCILjPkJu/kDfnYFUETtVzeT4unx0ZMM4FmZG387n6IhOqAIX7fDKUHQe8LuQx6EfKGZpOBmzG8hyiuL/NXnbNapKHaDh4/6k6h0x0TztFEa7gytWMNN48OsnQjgPXIdOu8aXYeu/w5AeIp8kmpkJsU6KL3FrtRCVQTvNEgVxsFQy6sFddxvd6QBQQyW6GmIIcSsdsnG43qCkQIU1zcnwJ8izGQU4X+M706LVLCOLhiwrRt72Fsl1E/5NNvSm1enKvgW6oMi+CiR2W/iejx8YX7Dd1lvcb8dyOi0uJhK+e8smf2JTjNjM1zpmYz5eDEE6bO/+q4J/YKMiBFGzJdUCrpMICXYv/WnV0VeuAEGYvH00uP+bz4PD+6Gx6CRVGFq7Jd/GzRby0p4hSqoyQm/T0Ybapj0KuySwKYsq/zaVmyJYdHkPVMfyoDIsYK3c308ETrGeKDM2WuI3TrCvMqvCfZ62fKH4Z0nqzG1JztS8gBdWEiKMu2EXJMK2oKAZEEObj2/qq+bznG4nx1pkW2rVI1QxIcWuDOVZRMrIdkfDAl9V5TfAUF9O94rpNKEnR4XbLvQzTYGqXA2Zay2OkeoVP1wC6owsCJXKBok3SPentiOa8Mc2itEziS7dgCYptC6agDL5mZumspcWquWErvTu5g/v3iS9fV7QwmNzQaguPgAEVAgAACjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAowMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAowMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMApjbGVhcnRvbWFyawqAAw==") format("woff"), url("../fonts/ajs-webfont.ttf?93a8957d9da533b23877909fab6d8fc2") format("truetype"); font-weight: normal; font-style: normal; } .ajs-icon { font-family: "ajs-webfont"; display: inline-block; vertical-align: middle; line-height: 1; font-weight: normal; font-style: normal; speak: none; text-decoration: inherit; text-transform: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } // Icons .ajs-icon-add-whole-segment() { &:before { content: "\f101"; } } .ajs-icon-add-whole-segment { .ajs-icon-add-whole-segment(); } .ajs-icon-amalia-js() { &:before { content: "\f102"; } } .ajs-icon-amalia-js { .ajs-icon-amalia-js(); } .ajs-icon-arrows-h() { &:before { content: "\f103"; } } .ajs-icon-arrows-h { .ajs-icon-arrows-h(); } .ajs-icon-arrows-v() { &:before { content: "\f104"; } } .ajs-icon-arrows-v { .ajs-icon-arrows-v(); } .ajs-icon-bell() { &:before { content: "\f105"; } } .ajs-icon-bell { .ajs-icon-bell(); } .ajs-icon-building() { &:before { content: "\f106"; } } .ajs-icon-building { .ajs-icon-building(); } .ajs-icon-caret-right() { &:before { content: "\f107"; } } .ajs-icon-caret-right { .ajs-icon-caret-right(); } .ajs-icon-check() { &:before { content: "\f108"; } } .ajs-icon-check { .ajs-icon-check(); } .ajs-icon-chevron-circle-down() { &:before { content: "\f109"; } } .ajs-icon-chevron-circle-down { .ajs-icon-chevron-circle-down(); } .ajs-icon-chevron-circle-left() { &:before { content: "\f10a"; } } .ajs-icon-chevron-circle-left { .ajs-icon-chevron-circle-left(); } .ajs-icon-chevron-circle-right() { &:before { content: "\f10b"; } } .ajs-icon-chevron-circle-right { .ajs-icon-chevron-circle-right(); } .ajs-icon-chevron-circle-up() { &:before { content: "\f10c"; } } .ajs-icon-chevron-circle-up { .ajs-icon-chevron-circle-up(); } .ajs-icon-chevron-down() { &:before { content: "\f10d"; } } .ajs-icon-chevron-down { .ajs-icon-chevron-down(); } .ajs-icon-chevron-left() { &:before { content: "\f10e"; } } .ajs-icon-chevron-left { .ajs-icon-chevron-left(); } .ajs-icon-chevron-right() { &:before { content: "\f10f"; } } .ajs-icon-chevron-right { .ajs-icon-chevron-right(); } .ajs-icon-chevron-up() { &:before { content: "\f110"; } } .ajs-icon-chevron-up { .ajs-icon-chevron-up(); } .ajs-icon-circle() { &:before { content: "\f111"; } } .ajs-icon-circle { .ajs-icon-circle(); } .ajs-icon-cog() { &:before { content: "\f112"; } } .ajs-icon-cog { .ajs-icon-cog(); } .ajs-icon-cogs() { &:before { content: "\f113"; } } .ajs-icon-cogs { .ajs-icon-cogs(); } .ajs-icon-comment() { &:before { content: "\f114"; } } .ajs-icon-comment { .ajs-icon-comment(); } .ajs-icon-compress() { &:before { content: "\f115"; } } .ajs-icon-compress { .ajs-icon-compress(); } .ajs-icon-control-backward() { &:before { content: "\f116"; } } .ajs-icon-control-backward { .ajs-icon-control-backward(); } .ajs-icon-control-fast-forward() { &:before { content: "\f117"; } } .ajs-icon-control-fast-forward { .ajs-icon-control-fast-forward(); } .ajs-icon-control-fast-rewind() { &:before { content: "\f118"; } } .ajs-icon-control-fast-rewind { .ajs-icon-control-fast-rewind(); } .ajs-icon-control-forward() { &:before { content: "\f119"; } } .ajs-icon-control-forward { .ajs-icon-control-forward(); } .ajs-icon-control-pause() { &:before { content: "\f11a"; } } .ajs-icon-control-pause { .ajs-icon-control-pause(); } .ajs-icon-control-play() { &:before { content: "\f11b"; } } .ajs-icon-control-play { .ajs-icon-control-play(); } .ajs-icon-control-rewind() { &:before { content: "\f11c"; } } .ajs-icon-control-rewind { .ajs-icon-control-rewind(); } .ajs-icon-controlbar-compress() { &:before { content: "\f11d"; } } .ajs-icon-controlbar-compress { .ajs-icon-controlbar-compress(); } .ajs-icon-controlbar-fullscreen() { &:before { content: "\f11e"; } } .ajs-icon-controlbar-fullscreen { .ajs-icon-controlbar-fullscreen(); } .ajs-icon-controlbar-pause() { &:before { content: "\f11f"; } } .ajs-icon-controlbar-pause { .ajs-icon-controlbar-pause(); } .ajs-icon-controlbar-play() { &:before { content: "\f120"; } } .ajs-icon-controlbar-play { .ajs-icon-controlbar-play(); } .ajs-icon-controlbar-settings() { &:before { content: "\f121"; } } .ajs-icon-controlbar-settings { .ajs-icon-controlbar-settings(); } .ajs-icon-controlbar-volume-left-off() { &:before { content: "\f122"; } } .ajs-icon-controlbar-volume-left-off { .ajs-icon-controlbar-volume-left-off(); } .ajs-icon-controlbar-volume-left() { &:before { content: "\f123"; } } .ajs-icon-controlbar-volume-left { .ajs-icon-controlbar-volume-left(); } .ajs-icon-controlbar-volume-min() { &:before { content: "\f124"; } } .ajs-icon-controlbar-volume-min { .ajs-icon-controlbar-volume-min(); } .ajs-icon-controlbar-volume-off() { &:before { content: "\f125"; } } .ajs-icon-controlbar-volume-off { .ajs-icon-controlbar-volume-off(); } .ajs-icon-controlbar-volume-right-off() { &:before { content: "\f126"; } } .ajs-icon-controlbar-volume-right-off { .ajs-icon-controlbar-volume-right-off(); } .ajs-icon-controlbar-volume-right() { &:before { content: "\f127"; } } .ajs-icon-controlbar-volume-right { .ajs-icon-controlbar-volume-right(); } .ajs-icon-controlbar-volume_max() { &:before { content: "\f128"; } } .ajs-icon-controlbar-volume_max { .ajs-icon-controlbar-volume_max(); } .ajs-icon-controlbar-volume_middle() { &:before { content: "\f129"; } } .ajs-icon-controlbar-volume_middle { .ajs-icon-controlbar-volume_middle(); } .ajs-icon-download() { &:before { content: "\f12a"; } } .ajs-icon-download { .ajs-icon-download(); } .ajs-icon-eject() { &:before { content: "\f12b"; } } .ajs-icon-eject { .ajs-icon-eject(); } .ajs-icon-ellipsis-h() { &:before { content: "\f12c"; } } .ajs-icon-ellipsis-h { .ajs-icon-ellipsis-h(); } .ajs-icon-ellipsis-v() { &:before { content: "\f12d"; } } .ajs-icon-ellipsis-v { .ajs-icon-ellipsis-v(); } .ajs-icon-eraser() { &:before { content: "\f12e"; } } .ajs-icon-eraser { .ajs-icon-eraser(); } .ajs-icon-expand() { &:before { content: "\f12f"; } } .ajs-icon-expand { .ajs-icon-expand(); } .ajs-icon-eye-off() { &:before { content: "\f130"; } } .ajs-icon-eye-off { .ajs-icon-eye-off(); } .ajs-icon-eye-on() { &:before { content: "\f131"; } } .ajs-icon-eye-on { .ajs-icon-eye-on(); } .ajs-icon-facetime() { &:before { content: "\f132"; } } .ajs-icon-facetime { .ajs-icon-facetime(); } .ajs-icon-female() { &:before { content: "\f133"; } } .ajs-icon-female { .ajs-icon-female(); } .ajs-icon-github() { &:before { content: "\f134"; } } .ajs-icon-github { .ajs-icon-github(); } .ajs-icon-information() { &:before { content: "\f135"; } } .ajs-icon-information { .ajs-icon-information(); } .ajs-icon-jogs-backward-0x() { &:before { content: "\f136"; } } .ajs-icon-jogs-backward-0x { .ajs-icon-jogs-backward-0x(); } .ajs-icon-jogs-backward-1x() { &:before { content: "\f137"; } } .ajs-icon-jogs-backward-1x { .ajs-icon-jogs-backward-1x(); } .ajs-icon-jogs-backward-2x() { &:before { content: "\f138"; } } .ajs-icon-jogs-backward-2x { .ajs-icon-jogs-backward-2x(); } .ajs-icon-jogs-backward-3x() { &:before { content: "\f139"; } } .ajs-icon-jogs-backward-3x { .ajs-icon-jogs-backward-3x(); } .ajs-icon-jogs-backward-4x() { &:before { content: "\f13a"; } } .ajs-icon-jogs-backward-4x { .ajs-icon-jogs-backward-4x(); } .ajs-icon-jogs-center() { &:before { content: "\f13b"; } } .ajs-icon-jogs-center { .ajs-icon-jogs-center(); } .ajs-icon-jogs-fast-backward() { &:before { content: "\f13c"; } } .ajs-icon-jogs-fast-backward { .ajs-icon-jogs-fast-backward(); } .ajs-icon-jogs-fast-forward() { &:before { content: "\f13d"; } } .ajs-icon-jogs-fast-forward { .ajs-icon-jogs-fast-forward(); } .ajs-icon-jogs-forward-0x() { &:before { content: "\f13e"; } } .ajs-icon-jogs-forward-0x { .ajs-icon-jogs-forward-0x(); } .ajs-icon-jogs-forward-1x() { &:before { content: "\f13f"; } } .ajs-icon-jogs-forward-1x { .ajs-icon-jogs-forward-1x(); } .ajs-icon-jogs-forward-2x() { &:before { content: "\f140"; } } .ajs-icon-jogs-forward-2x { .ajs-icon-jogs-forward-2x(); } .ajs-icon-jogs-forward-3x() { &:before { content: "\f141"; } } .ajs-icon-jogs-forward-3x { .ajs-icon-jogs-forward-3x(); } .ajs-icon-jogs-forward-4x() { &:before { content: "\f142"; } } .ajs-icon-jogs-forward-4x { .ajs-icon-jogs-forward-4x(); } .ajs-icon-key() { &:before { content: "\f143"; } } .ajs-icon-key { .ajs-icon-key(); } .ajs-icon-legal() { &:before { content: "\f144"; } } .ajs-icon-legal { .ajs-icon-legal(); } .ajs-icon-list-close() { &:before { content: "\f145"; } } .ajs-icon-list-close { .ajs-icon-list-close(); } .ajs-icon-list-open() { &:before { content: "\f146"; } } .ajs-icon-list-open { .ajs-icon-list-open(); } .ajs-icon-lock-close() { &:before { content: "\f147"; } } .ajs-icon-lock-close { .ajs-icon-lock-close(); } .ajs-icon-lock-open() { &:before { content: "\f148"; } } .ajs-icon-lock-open { .ajs-icon-lock-open(); } .ajs-icon-male() { &:before { content: "\f149"; } } .ajs-icon-male { .ajs-icon-male(); } .ajs-icon-microphone-off() { &:before { content: "\f14a"; } } .ajs-icon-microphone-off { .ajs-icon-microphone-off(); } .ajs-icon-microphone-on() { &:before { content: "\f14b"; } } .ajs-icon-microphone-on { .ajs-icon-microphone-on(); } .ajs-icon-minus() { &:before { content: "\f14c"; } } .ajs-icon-minus { .ajs-icon-minus(); } .ajs-icon-music() { &:before { content: "\f14d"; } } .ajs-icon-music { .ajs-icon-music(); } .ajs-icon-picture() { &:before { content: "\f14e"; } } .ajs-icon-picture { .ajs-icon-picture(); } .ajs-icon-plus() { &:before { content: "\f14f"; } } .ajs-icon-plus { .ajs-icon-plus(); } .ajs-icon-power() { &:before { content: "\f150"; } } .ajs-icon-power { .ajs-icon-power(); } .ajs-icon-refresh() { &:before { content: "\f151"; } } .ajs-icon-refresh { .ajs-icon-refresh(); } .ajs-icon-remove() { &:before { content: "\f152"; } } .ajs-icon-remove { .ajs-icon-remove(); } .ajs-icon-reorder() { &:before { content: "\f153"; } } .ajs-icon-reorder { .ajs-icon-reorder(); } .ajs-icon-screenshot() { &:before { content: "\f154"; } } .ajs-icon-screenshot { .ajs-icon-screenshot(); } .ajs-icon-scrubber-cursor() { &:before { content: "\f155"; } } .ajs-icon-scrubber-cursor { .ajs-icon-scrubber-cursor(); } .ajs-icon-search() { &:before { content: "\f156"; } } .ajs-icon-search { .ajs-icon-search(); } .ajs-icon-sign-in() { &:before { content: "\f157"; } } .ajs-icon-sign-in { .ajs-icon-sign-in(); } .ajs-icon-sign-out() { &:before { content: "\f158"; } } .ajs-icon-sign-out { .ajs-icon-sign-out(); } .ajs-icon-sort() { &:before { content: "\f159"; } } .ajs-icon-sort { .ajs-icon-sort(); } .ajs-icon-sound-link-off() { &:before { content: "\f15a"; } } .ajs-icon-sound-link-off { .ajs-icon-sound-link-off(); } .ajs-icon-sound-link-on() { &:before { content: "\f15b"; } } .ajs-icon-sound-link-on { .ajs-icon-sound-link-on(); } .ajs-icon-stop() { &:before { content: "\f15c"; } } .ajs-icon-stop { .ajs-icon-stop(); } .ajs-icon-transcription() { &:before { content: "\f15d"; } } .ajs-icon-transcription { .ajs-icon-transcription(); } .ajs-icon-volume-down() { &:before { content: "\f15e"; } } .ajs-icon-volume-down { .ajs-icon-volume-down(); } .ajs-icon-volume-off() { &:before { content: "\f15f"; } } .ajs-icon-volume-off { .ajs-icon-volume-off(); } .ajs-icon-volume-up() { &:before { content: "\f160"; } } .ajs-icon-volume-up { .ajs-icon-volume-up(); } .ajs-icon-zoom-in() { &:before { content: "\f161"; } } .ajs-icon-zoom-in { .ajs-icon-zoom-in(); } .ajs-icon-zoom-out() { &:before { content: "\f162"; } } .ajs-icon-zoom-out { .ajs-icon-zoom-out(); } ================================================ FILE: src/assets/less/default-style.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-tooltip { font-family: Arial, Helvetica, sans-serif; color: #fff; background: #0cf; padding: 10px 5px 10px 5px; max-width: 300px; box-shadow: none; border: none; margin-top: -50px; &:after { content: ""; position: absolute; left: 50%; top: -20px; width: 15px; height: 15px; box-shadow: none; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); tranform: rotate(45deg); border: none; background: #0cf; margin-left: -7.5px; } } .ui-tooltip { padding: 8px; position: absolute; z-index: 9999; max-width: 300px; -webkit-box-shadow: 0 0 5px #aaa; box-shadow: 0 0 5px #aaa; } .ui-helper-hidden-accessible { display: none; } ================================================ FILE: src/assets/less/default.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /************************************************** ****************** LESS VARIABLES ***************** **************************************************/ /***** FONTS ****/ @fontMain: Arial, Helvetica, sans-serif; /***** COLORS ****/ @BtToolContColor : #6c6c6c; /************************************************** ****************** THEMES PROJETS ***************** **************************************************/ /***** PLAYER PROJET GEN ****/ @mainColor: #0CF; @mainBackgroundColor: rgba(19, 231, 240, 0.68); @mainGradient: linear-gradient(to right, #13e7f0, #0c7abf); @inverseBackgroundColor: rgba(51, 51, 51, 0.68); /***** PLAYER TEXTE SYNCRO SNOOPDIC ****/ /* @mainColor: #0CF; @mainBackgroundColor: rgba(19, 231, 240, 0.68); @mainGradient: linear-gradient(to right, #13e7f0, #0c7abf); */ /***** PLAYER TEXTE SYNCRO ****/ /* @mainColor: #bf009a; @mainBackgroundColor: rgba(191, 0, 154, 0.6); @mainGradient: linear-gradient(to right, #e55ac9, #96047b); */ @import "ajs-animations"; @import "ajs-webfont"; @import "default-style"; @import "player"; @import "plugin"; ================================================ FILE: src/assets/less/player-custom-control-bar.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin custom control bar */ .ajs .plugin-custom-controlbar { width: 100%; background-color: #1d1d1d; background-image: -webkit-gradient(linear, 100% 0, 0 100%, from(#232323), to(#1d1d1d)); background-image: -webkit-linear-gradient(top, #232323 0%, #1d1d1d 100%); background-image: -moz-linear-gradient(top, #232323 0%, #1d1d1d 100%); background-image: -o-linear-gradient(top, #232323 0%, #1d1d1d 100%); background-image: linear-gradient(#232323, #1d1d1d); overflow: visible; margin-bottom: 0px; z-index: 900; position: relative; opacity: .9; .ajs-row { margin: 0px; &:before { content: " "; display: table; } .ajs-container { width: 33.33333333%; float: left; position: relative; min-height: 1px; padding: 0px; margin: 0px; height: 110px; &.left-container { } &.middle-container { } &.right-container { } } } .player-base-button { background-color: none; line-height: 110px; margin: 0 auto; text-align: center; width: 120px; color: #fff; float: right; cursor: pointer; } .player-play-button, .player-pause-button { background-color: none; line-height: 110px; margin: 0 auto; text-align: center; width: 120px; color: #fff; &.on { display: block; } &.off { display: none; } span.button-container { background: #191919; border: 1px solid #4d4d4d; border-radius: 50%; cursor: pointer; display: inline-block; height: 90px; width: 90px; line-height: 95px; margin: auto; position: relative; vertical-align: middle; padding: 0px; font-size: 2em; @media (max-width: 668px) { line-height: 70px; height: 70px; width: 70px; padding-top: 1px; font-size: 1.5em; } &:hover { background: #000; } } } .player-label { display: inline-block; width: 160px; line-height: 30px; margin-left: 3px; margin-right: 3px; height: 28px; background: none; } .player-timelabel.time-display { display: block; height: 100px; float: left; line-height: 40px; padding: 25px 0 0 10px; .time-current { color: white; display: block; font-size: 2.5em; @media (max-width: 668px) { font-size: 1.5em; } } .time-separator { display: block; height: 1px; } .time-duration { color: white; display: block; text-align: right; } } .player-fullscreen-button { width: 50px; display: inline-block; vertical-align: middle; text-align: center; line-height: 100px; color: #fff; margin: 10px 0 0 20px; cursor: pointer; width: 50px; display: inline-block; vertical-align: middle; text-align: center; line-height: 100px; color: #fff; margin: 10px 0 0 20px; cursor: pointer; float: right; font-size: 2.4em; } .player-volume-control { vertical-align: middle; padding-top: 25px; cursor: pointer; float: right; font-size: 2em; @media (max-width: 567px) { display: none; } .volume-control-btn { position: absolute; top: 0; margin-left: 22px; margin-top: 48px; color: #FFF; height: 50px; /*width: 30px;*/ line-height: 30px; display: block; /*bottom: -51px;*/ text-align: center; cursor: pointer; } } .player-progress-bar { height: 20px; margin-bottom: 0px; overflow: hidden; background-color: #6a6969; border-radius: 0px; clear: both; position: relative; text-align: left; color: #404040; .buffer-bar { display: block; height: 100%; background-color: #555; position: relative; top: 0px; box-sizing: border-box; width: 0px; } .ui-slider-range { float: left; width: 0; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; background-color: #58c8b0; position: absolute; z-index: 1; display: block; border: 0; background-position: 0 0; } .ui-slider-handle { background-color: #fff; border-radius: 0%; cursor: pointer; float: right; height: 25px; right: 0; width: 25px; z-index: 2; text-shadow: none; top: -.3em; margin-left: -.6em; position: absolute; background-color: #e6e6e6; background-repeat: no-repeat; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); color: #333; font-size: 13px; line-height: normal; border: 1px solid #ccc; border-bottom-color: #bbb; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -webkit-transition: 0.1s linear background-image; -moz-transition: 0.1s linear background-image; -ms-transition: 0.1s linear background-image; -o-transition: 0.1s linear background-image; transition: 0.1s linear background-image; overflow: visible; } &.ui-slider .ui-slider-range { background: @mainGradient; float: left; width: 0; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; left: 0; top: 0; position: absolute; z-index: 1; display: block; border: 0; background-position: 0 0; color: #ffffff; background-color: #0064cd; background-repeat: repeat-x; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); border-color: #0064cd #0064cd #003f81; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); } &.ui-widget-content { background: #6c6c6c; border: none; } } .player-channel-volume-control { padding-top: 0; cursor: pointer; float: left; height: 35px; width: 35px; line-height: 30px; color: #fff; .volume-control-btn { vertical-align: middle; padding-top: 15px; top: 0; margin-left: 54px; margin-top: 8px; height: 35px; line-height: 30px; display: block; font-size: 35px; } .channel-volume-sliders { position: absolute; bottom: 10px; padding-left: 0px; height: 211px; background-repeat: no-repeat; left: 24px; display: none; background: linear-gradient(90deg, #666666 50%, #797979 50%); &.on { display: block; } .channel-volume-info { display: block; position: relative; padding-left: 5px; .channel-volume-info-left, .channel-volume-info-right { width: 38px; height: 40px; color: #fff; float: left; text-align: center; margin-left: 0px; font-size: 25px; padding-left: 2px; } .channel-volume-info-left { text-align: left; } .channel-volume-info-right { text-align: center; } .channel-volume-info-mid { width: 12px; height: 40px; color: #fff; float: left; text-align: center; padding-top: 10px; left: 30px; margin-left: 0px; .unify { color: #EEE; font-size: 23px; font-weight: bold; margin: -10px; &.on { color: cadetblue; } } } } .channel-volume-control { display: block; margin: 0px; .channel-volume-control-left, .channel-volume-control-right { height: 145px; color: #fff; float: left; width: 30px; margin-left: 19px; .ui-state-focus, .ui-state-hover { background-color: cadetblue; } .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 18px; height: 18px; cursor: default; -ms-touch-action: none; touch-action: none; border-radius: 100%; } .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #999999; background: #999999; font-weight: normal; color: #454545; } .ui-slider-vertical { width: 4px; height: 140px; } .ui-widget-content { border: 1px solid #FFF; background: #fff; color: #333; } .ui-slider-vertical .ui-slider-handle { left: -8px; margin-left: 0; margin-bottom: -.6em; } } .channel-volume-control-mid { width: 35px; height: 3px; background-color: #999; clear: both; background-repeat: no-repeat; margin-left: 5px; position: absolute; visibility: hidden; left: 24px; top: 49px; &.on { visibility: visible; } } } } } .player-jog-shuttle-button { line-height: 30px; color: #fff; float: left; display: block; width: 240px; position: relative; border: 1px solid #cacaca; border-radius: 20px; height: 38px; top: 18px; span.button-container { border: none; border-radius: 0%; display: inline-block; height: 32px; line-height: 40px; font-size: 35px; width: 100%; position: relative; top: 2px; .jog-shuttle-separator { display: inline-block; width: 2px; background-color: #eee; height: 32px; } .backward-container, .forward-container { height: 32px; display: inline-block; line-height: 30px; float: none; color: rgba(238, 238, 238, 0.25); margin-top: 4px; padding-right: 5px; padding-left: 5px; span { height: 32px; padding-left: 10px; padding-right: 10px; position: absolute; color: #66cc99; &.ajs-icon-jogs-forward-0x, &.ajs-icon-jogs-backward-0x { visibility: hidden; } &.ajs-icon-jogs-backward-1x, &.ajs-icon-jogs-backward-2x, &.ajs-icon-jogs-backward-3x, &.ajs-icon-jogs-backward-4x, &.ajs-icon-jogs-fast-backward { left: 0; } &.ajs-icon-jogs-forward-1x, &.ajs-icon-jogs-forward-2x, &.ajs-icon-jogs-forward-3x, &.ajs-icon-jogs-forward-4x, &.ajs-icon-jogs-fast-forward { color: #66cc99; right: -5px; top: 1px; } &.ajs-icon-jogs-backward-1x, &.ajs-icon-jogs-backward-2x, &.ajs-icon-jogs-backward-3x, &.ajs-icon-jogs-backward-4x, &.ajs-icon-jogs-fast-backward { color: #66cc99; left: -5px; top: 1px; } } } .backward-container { float: left; text-align: left; border: none; width: 74px; } .forward-container { float: right; text-align: right; width: 74px; } .jog-shuttle { background-color: transparent; border-radius: 20px; position: absolute; width: 151px; top: 0px; height: 32px; margin-left: 43px; -webkit-transition: opacity 0.5s ease-in; -moz-transition: opacity 0.5s ease-in; -o-transition: opacity 0.5s ease-in; -ms-transition: opacity 0.5s ease-in; transition: opacity 0.5s ease-in; display: none; border: none; &.on { display: block; } span.ui-slider-handle { border: 1px solid; top: -8px; margin: 0; position: absolute; z-index: 2; cursor: pointer; padding: 0; border-radius: 100%; background-color: #1D1D1D; height: 48px; width: 50px; line-height: 30px; margin-left: -25px; font-size: 48px; color: #eee; font-weight: normal; } } } } &.sticky { background-image: none; opacity: 1; .ajs-row { .ajs-container { height: 35px; &.left-container { } &.middle-container { text-align: center; } &.right-container { } } } .player-base-button { line-height: 25px; width: 35px; height: 35px; vertical-align: middle; text-align: center; padding-top: 5px; float: none; display: inline-block; font-size: 1.4em; } .player-play-button, .player-pause-button { line-height: 30px; width: 35px; color: #fff; display: block; &.on { display: inline-block; } &.off { display: none; } span.button-container { border: none; border-radius: 0%; display: inline-block; height: 35px; width: 35px; line-height: 40px; font-size: 35px; } } .player-timelabel.time-display { display: inline-block; line-height: 35px; padding: 0px 0px 0px 10px; height: 35px; .time-current { color: white; display: inline-block; font-size: 1em; @media (max-width: 567px) { font-size: 0.8em; } } .time-separator { display: inline-block; color: white; padding-left: 5px; padding-right: 5px; font-size: 0.9em; &:before { content: "/"; } @media (max-width: 567px) { display: none; } } .time-duration { display: inline-block; font-size: 0.9em; @media (max-width: 567px) { display: none; } } } .player-timelabel.time-display.off { .time-separator { display: none; } } .player-fullscreen-button { display: inline-block; color: #fff; cursor: pointer; width: 35px; line-height: 18px; margin: 5px 10px 0px 35px; float: right; font-size: 2.4em; } .player-volume-control { padding-top: 0; cursor: pointer; float: right; height: 35px; width: 35px; line-height: 25px; canvas { display: none } .volume-control-btn { top: 0; margin-left: 22px; margin-top: 5px; height: 35px; line-height: 30px; display: block; font-size: 1.4em; } } .player-progress-bar { height: 10px; .buffer-bar { } .ui-slider-range { line-height: 20px; } .ui-slider-handle { height: 15px; width: 10px; } } } } ================================================ FILE: src/assets/less/player.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Player */ /** * Plugin control bar */ .ajs { overflow: hidden; font-family: @fontMain; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; line-height: 0px; .ajs-loader { color: white; position: absolute; z-index: 100; text-align: center; width: 100%; height: 100%; top: 50%; } .ajs-error { position: absolute; z-index: 100; width: 100%; height: 100%; background-color: black; color: white; vertical-align: middle; text-align: center; line-height: 20px; top: 0; p { margin-left: auto; margin-right: auto; position: relative; top: 50%; margin-top: -25px; } } /* Reset background with font Awesome */ .ajs .ui-state-default .ui-icon[class*=" fa-"] { background: none; text-indent: 0; } } /**tooltip**/ .ui-tooltip { font-family: @fontMain; padding: 5px 5px; color: white; border: none; box-shadow: none; border: none; box-shadow: none; background: @mainColor; p { font-size: 14px; margin: 0; } .timeline-images-component { padding: 3px; &.tooltip-image { width: 200px; } } } .ajs-arrow { width: 70px; height: 16px; overflow: hidden; position: absolute; left: 50%; margin-left: -35px; bottom: -16px; border: none; &:after { content: ""; position: absolute; left: 20px; top: -20px; width: 25px; height: 25px; box-shadow: none; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); tranform: rotate(45deg); border: none; background: @mainColor; } &.top { top: -16px; bottom: auto; &:after { bottom: -20px; top: auto; } } &.left { left: 20%; } } .inalabplayer-ui-resizable-helper { z-index: 9999; border: 1px dashed #6c6c6c !important; } ================================================ FILE: src/assets/less/plugin-captions.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin caption */ .ajs-plugin.plugin-caption { display: block; color: #FFF; position: absolute; bottom: 65px; line-height: 20px; text-align: center; width: 100%; background-color: @inverseBackgroundColor; min-height: 20px; z-index: 98; padding-left: 0; padding-right: 0; font-size: 1.4em; &.fullScreenOn { font-size: 3em; line-height: 45px; } &.fullScreenOff { font-size: 1.4em; } } ================================================ FILE: src/assets/less/plugin-editor.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.editor { position: relative; .loader { position: absolute; top: 110px; z-index: 100; left: 0; right: 0; margin: 0; padding: 0; } /** * Plugin list editor */ &.plugin-list-editor { color: #666; .heading { height: 30px; border: none; line-height: 25px; background-color: #616161; color: #CCC; .title { text-align: left; padding-left: 10px; margin: 0; color: #FFF; line-height: 30px; font-size: 14px; } } .body { ul.listOfmetadata { box-sizing: border-box; color: #cacaca; display: block; font-size: 14px; line-height: 20px; list-style-type: disc; margin-bottom: 0px; margin-top: 0px; padding-left: 0px; height: 90px; overflow-y: overlay; li.item { position: relative; display: block; padding: 5px 15px; margin: 0; background-color: #eceff1; border: none; color: #000; font-size: 11px; &.selected { background-color: #546e7a; color: rgba(255, 255, 255, 0.87); } span.delete { float: right; padding: 0px; font-size: 10px; color: #fff; text-align: center; white-space: nowrap; background-color: #E57373; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 20px; width: 20px; margin: auto; position: relative; vertical-align: middle; box-shadow: none; line-height: 23px; margin-left: 5px; &:before { margin-left: -1px; } } span.duplicate { float: right; padding: 0px; font-size: 10px; color: #fff; text-align: center; white-space: nowrap; background-color: #3cf; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 20px; width: 20px; margin: auto; position: relative; vertical-align: middle; box-shadow: none; line-height: 23px; &:before { margin-left: -1px; } } } } } .footer { height: 25px; border: none; line-height: 25px; background-color: #616161; color: #CCC; text-align: center; .add-metadata { min-width: 10px; font-size: 25px; font-weight: normal; color: #fff; text-align: center; white-space: nowrap; background-color: #00CC99; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 35px; width: 35px; margin: auto; position: relative; vertical-align: middle; margin-top: -25px; box-shadow: none; line-height: 40px; text-align: left; &:before { margin-left: -1px; } } } } /** * Plugin block editor */ &.plugin-block-editor { color: #666; .heading { height: 30px; border: none; line-height: 25px; background-color: #616161; color: #CCC; .title { text-align: left; padding-left: 10px; margin: 0; color: #FFF; line-height: 30px; font-size: 14px; } } .body { padding: 5px 5px 15px 5px; form.formMetadataBlock { .form-item { padding: 0px; margin: 0px; box-shadow: none; font-size: 12px; .input { width: 100%; border: none; box-shadow: none; background-color: #eaeaea; color: #000; height: 25px; padding-left: 5px; border-radius: 0px; font-size: 12px; } .text-area { width: 100%; height: 50px; border-radius: 3px; border: 1px solid #ccc; display: inline-block; padding: 4px; font-size: 12px; } .select { width: 100%; border: none; box-shadow: none; background-color: #eaeaea; color: #000; height: 25px; padding-left: 5px; border-radius: 0px; font-size: 12px; } .shape.ajs-icon { font-size: 20px; } } } .messages-container { padding: 0px; margin-bottom: 0px; border: none; border-radius: 4px; background-color: #E1F5FE; margin-top: 0px; text-align: center; &.type-info { background-color: #E1F5FE; } &.type-error { background-color: #EF9A9A; } p.info { padding: 0px; margin: 0px; } p.error { padding: 0px; margin: 0px; } } } .footer { height: 25px; border: none; line-height: 25px; background-color: #616161; color: #CCC; text-align: center; .save-metadata { min-width: 10px; padding: 0; font-size: 25px; font-weight: normal; color: #fff; text-align: center; white-space: nowrap; background-color: #03A9F4; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 35px; width: 35px; margin: auto; position: relative; vertical-align: middle; margin-top: -25px; box-shadow: none; line-height: 40px; &:before { margin-left: -1px; } } } } /** * Plugin items editor */ &.plugin-items-editor { color: #616161; .heading { height: 30px; border: none; line-height: 25px; background-color: #616161; color: #CCC; .title { text-align: left; padding-left: 10px; margin: 0; color: #FFF; line-height: 30px; font-size: 14px; } } .body { .messages-container { padding: 5px 0px 5px 0px; margin-bottom: 11px; border: none; border-radius: 4px; background-color: #E1F5FE; margin-top: 10px; text-align: center; min-height: 25px; &.type-info { background-color: #E1F5FE; } &.type-error { background-color: #EF9A9A; } p.info { padding: 0px; margin: 0px; } p.error { padding: 0px; margin: 0px; } } ul.listOfSelectedItems { box-sizing: border-box; color: #cacaca; display: block; font-size: 14px; line-height: 20px; list-style-type: disc; margin-bottom: 0px; margin-top: 0px; padding-left: 0px; height: 285px; overflow-y: overlay; li.item { position: relative; display: block; padding: 0px; margin-bottom: 0; background-color: transparent; border: none; color: #000; box-shadow: none; font-size: 12px; &.error { border: 1px solid red; text-align: left; } .form-data { padding: 25px 0px 10px 0px; border: none; background-color: #eceff1; margin-right: 0; min-height: 56px; box-shadow: none; margin: 1px 0px 0px 0px; .form-input { margin: 0px 5px; box-shadow: none; min-height: 25px; .input { width: 100%; border: none; box-shadow: none; background-color: #eaeaea; color: #000; height: 25px; padding-left: 5px; border-radius: 5px; font-size: 12px; } } .form-controls { position: absolute; width: auto; height: 25px; top: 5px; right: 10px; padding: 0px; span.button { padding: 0px; font-size: 12px; font-weight: normal; text-align: center; white-space: nowrap; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 20px; width: 20px; margin: 0px 0px 0px 5px; position: relative; vertical-align: middle; padding-top: 0px; margin-top: 0; top: 0px; right: 0px; color: white; box-shadow: none; line-height: 23px; opacity: 1; filter: none; float: none; &:before { margin-left: -1px; } &.valid { background-color: #CACACA; visibility: hidden; &.valid.on { visibility: visible; background-color: #03A9F4; } } &.remove { background-color: #FFC107; } &.close { background-color: #757575; } } } } } } } .footer { height: 25px; border: none; line-height: 25px; background-color: #616161; color: #CCC; text-align: center; .button { min-width: 10px; font-size: 25px; font-weight: normal; color: #fff; text-align: center; white-space: nowrap; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 35px; width: 35px; margin: 5px; position: relative; vertical-align: middle; margin-top: -25px; box-shadow: none; line-height: 40px; &.add { background-color: #00CC99; &:before { margin-left: -1px; } } &.validateAll { background-color: #03A9F4; &:before { margin-left: -1px; } } &.clear { background-color: #757575; &:before { margin-left: -1px; } } } } } } ================================================ FILE: src/assets/less/plugin-menu-contextuel.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** Plugin menu contextuel**/ .ajs .plugin-context-menu.dropdown-menu { width: 300px; padding: 0px 0px 0px 10px; margin: 0; text-align: left; list-style: none; background-color: #fff; -webkit-background-clip: padding-box; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, .15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); box-shadow: 0 6px 12px rgba(0, 0, 0, .175); z-index: 1000; &:before { bottom: -14px; border-top: 7px solid #555; } &:before, &:after, li:first-child:after { content: ''; display: block; position: absolute; left: 15px; width: 0; height: 0; border: 7px outset transparent; } li { color: #838ca2; text-shadow: none; margin: 0; padding: 0px 0px 0px 25px; border: 0; font-size: 100%; font: inherit; vertical-align: middle; height: 30px; list-style: none; line-height: 30px; display: block; position: relative; .ajs-icon { position: absolute; left: 0px; top: 3px; font-size: 24px; line-height: 28px; } &.disabled { a { cursor: default; } } } } ================================================ FILE: src/assets/less/plugin-overlay.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin overlay */ .ajs-plugin { &.plugin-overlay { display: block; color: #FFF; position: absolute; width: 100%; height: 100%; z-index: 98; top: 0; &.eraser { cursor: pointer; } .overlay-canvas { /*border: 1px solid red;*/ } .error { position: absolute; top: 9px; left: 0; width: 100%; line-height: 20px; color: white; font-size: 20px; background-color: red; font-weight: bold; } &.draw { cursor: crosshair; } .toolbox { width: 100px; position: absolute; top: 0; right: 0; border: none; padding: 0; margin: 0; cursor: move; opacity: 0.9; .add { .add-ctrl, .close-box, .add-shape-msg, .add-shape-rectangle, .add-shape-ellipse { height: 65px; width: 101px; background-color: #616161; color: white; font-size: 12px; line-height: 20px; text-align: center; box-shadow: 1px 1px 0px rgb(121, 121, 121); &.on { background-color: #99CC00; } } .add-shape-rectangle, .add-shape-ellipse { font-size: 50px; line-height: 75px; } .add-ctrl { background-color: #616161; .ctrl { background-color: #3cf; } } .close-box { background-color: #616161; .ctrl { background-color: transparent; border: 3px solid white; } } } .erase-box { height: 65px; width: 101px; background-color: rgba(49, 49, 49, 0.7); color: white; font-size: 12px; line-height: 20px; text-align: center; box-shadow: 1px 1px 0px rgb(121, 121, 121); &.on { background-color: #99CC00; } .ctrl { background-color: #E57373; } } .nav-box { background-color: rgba(121, 121, 121, 0.7); .nav-left-box, .nav-right-box { display: inline-block; text-align: center; width: 50px; height: 50px; margin: 0; padding: 0; line-height: 50px; .ctrl { margin: 0; padding: 0; &:hover { background-color: rgba(153, 204, 0, 0.7); } } } } .ctrl { height: 35px; width: 35px; display: inline-block; padding: 0px; font-size: 28px; color: #fff; text-align: center; white-space: nowrap; border: none; border-radius: 50%; cursor: pointer; margin: auto; position: relative; vertical-align: middle; box-shadow: none; line-height: 46px; margin: 10px 0px 0px 0px; border: 3px solid transparent; &.on { border: 3px solid rgb(153, 204, 0); } } .add-shapebox { background-color: rgba(49, 49, 49, 0.7); } } } } ================================================ FILE: src/assets/less/plugin-selected-item-editor.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.plugin-selected-item-editor { position: relative; .auto-fill-up-form { display: none; height: 60px; width: 700px; color: #000; background-color: #797979; position: absolute; bottom: 5px; z-index: 900; .message, .form-item { float: left; } .message { width: 520px; color: white; font-size: 16px; padding: 21px 0px 0px 18px; } .form-item { } &.on { display: block; } &:after { clear: both; } .form-item { .form-ctrl-item-yes { height: 60px; width: 90px; background-color: #1485cc; border: none; color: white; font-size: 16px; font-weight: bold; } .form-ctrl-item-no { height: 60px; width: 90px; background-color: #0b486c; border: none; color: white; font-size: 16px; font-weight: bold; } } } .form { height: 50px; width: 100%; color: #000; .form-item { float: left; .form-item-label { height: 60px; background-color: #f2f2f2; width: 170px; border: none; color: #666666; font-size: 16px; text-align: center; font-weight: normal; } .form-item-tcin, .form-item-tcout { height: 60px; width: 100px; border: none; color: #666666; font-size: 16px; text-align: center; &.error { background-color: #ba6868; } } .form-ctrl-item-tcin, .form-ctrl-item-tcout { background-color: #1485cc; border-radius: 0; color: #FFFFFF; display: block; font-size: 16px; height: 60px; line-height: 20px; padding: 10px; text-transform: uppercase; outline: none; width: 70px; border: none; padding: 0px; } .form-ctrl-item-valid { background-color: #797979; height: 60px; border: none; color: white; font-size: 16px; &.valid { background-color: #1485cc; } &:hover { background-color: #6ab6e8; } } .form-ctrl-item-delete { background-color: #B71C1C; height: 60px; border: none; color: white; font-size: 16px; display: none; &.on { display: block; } &:hover { background-color: #C62828; } } .form-ctrl-item-close-item { background-color: #B71C1C; height: 60px; border: none; color: white; font-size: 16px; display: none; &.on { display: block; } &:hover { background-color: #C62828; } } .form-ctrl-item-auto-fill-up { background-color: #a1a1a1; width: 60px; height: 60px; border: none; font-size: 52px; font-weight: 100; padding-top: 10px; color: white; &:hover { background-color: #6ab6e8; } } &.delete { display: none; &.on { display: block; } .form-ctrl-item-delete { background-color: #22baa0; } } &.label { background-color: #f2f2f2; padding: 0px; border: medium none; border-radius: 0; box-shadow: none; display: inline-block; margin: 0; border: none; } } } &.ajs-plugin { overflow: visible !important; } } ================================================ FILE: src/assets/less/plugin-storyboard.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.plugin-storyboard { display: none; color: #FFF; position: absolute; width: 100%; height: 100%; z-index: 98; top: 0; .thumbnail { height: 90px; width: 160px; background-color: #313131; background-position: 0px -90px; background-repeat: no-repeat; position: absolute; bottom: 45px; margin-top: 0px; margin-right: 0px; margin-bottom: 3px; left: 50%; border-radius: 2px; border: solid #000 2px; z-index: 90; } .filmstrip { position: absolute; width: 100%; text-align: center; margin: 0; padding: 0; opacity: 0.7; z-index: 90; -webkit-filter: grayscale(0.3); -moz-filter: grayscale(0.3); -ms-filter: grayscale(0.3); -o-filter: grayscale(0.3); .storyboard-thumbnail { background-color: #313131; background-position: 0px -90px; background-repeat: no-repeat; position: absolute; margin-top: 0px; margin-right: 0px; margin-bottom: 3px; border-radius: 2px; border: solid #000 2px; } } .preview-storyboard { text-align: center; display: block; position: absolute; margin: 0px; padding: 0px; .thumbnail-overlay { height: 100%; width: 100%; position: relative; border: solid #000 2px; visibility: visible; z-index: 80; filter: blur(5px); -webkit-filter: blur(3px) grayscale(0.8); -moz-filter: blur(3px) grayscale(0.8); -ms-filter: blur(3px) grayscale(0.8); -o-filter: blur(3px) grayscale(0.8); } } } ================================================ FILE: src/assets/less/plugin-text-sync.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin text sync */ .ajs-plugin.plugin-text-sync { background: #e6e6e6; margin: 0; padding: 0; color: black; .header { overflow: hidden; zoom: 1; display: block; margin: 0; padding: 0; .resume { background: #555; color: white; padding: 15px; text-align: left; font-size: 14px; overflow: hidden; zoom: 1; .heading { font-size: 24px; font-weight: 100; color: white; line-height: 1.1; padding: 0; margin: 0; } } } .line-component { padding: 10px; overflow-y: auto; height: 100%; margin: 0; .line { box-sizing: border-box; color: rgb(0, 0, 0); display: list-item; font-size: 14px; list-style-image: none; list-style-position: outside; list-style-type: none; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; overflow-x: hidden; overflow-y: hidden; text-align: left; padding: 10px; margin: 0; .info { box-sizing: border-box; color: rgb(0, 0, 0); display: block; float: left; font-family: Arial, Helvetica, sans-serif; font-size: 14px; margin-right: 10px; text-align: left; .thumb { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0IwMTkyREMwMTAwMTFFNDk0QTM5OTI4MzY1OEFGQUEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0IwMTkyREQwMTAwMTFFNDk0QTM5OTI4MzY1OEFGQUEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQjAxOTJEQTAxMDAxMUU0OTRBMzk5MjgzNjU4QUZBQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQjAxOTJEQjAxMDAxMUU0OTRBMzk5MjgzNjU4QUZBQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph56Pv8AAAJASURBVHja7JnLiupAEIY1BlG8492gK1HceseFD+0juNAHcCG6GlBBBVHEG15wfk5ARDj2JHYn00zVqglN1/91qquqE2en03HIbIpDciMAAiAAAiAAApDa1J9M0jStWCz6fD4rle33+9FoNJvNPgWA+nK5bP3WYr90v+8Z2CFUKBRsjBCmdzaA3++3EYDpXTW64vF4XK1W9/tdhFyn0xmNRr1eL+dD/Hywut3u9XoVmFVUtd1u/zxhGEuj8/lcqHoY1ocXUXXgdrtZEPeGvKgOWy2fz2cyGZyrwWBwOp1EFTJBlk6nS6USBqFQCKHf7/clayXC4fBjDAb5eqH1ev0YbzYbgb2QIEO2QejjDBwOh+FwKB8A7OufUTvNyVwuVzabVRRlMplcLhfJAKC+0Wigk8E4l8v1er3z+SzNjQzq6/W6rh4WCARarZbb7ZYDQFcfi8WeH74weDyeSqWCV2Q634sCQMTXarUX9S8MUI8B0mUikcAgEon8FgCor1ar8Xj8fxN0BtijPUbL0Gw2OTIoH6pPJpPvp4Hhpbnny2AeADHNVP/m1sKLwTxAKpX68ObFhcHOSsyFwTwAl7ulzvDcV1sHMJ1Oeb0H1IdgMGh1K4FOeLlc8vreiGS13W6t7oUWi4Xt3aixEDL0ycm0GfJiDEDTNNzEUcJEbaeiYH14ERVCevX9VRca+kNDAARAAAQgGGC329moj+mdDTAej20EYHpnV2L9N63EP7p1BuZCdIgJgAAIgAAIgAD+IsC3AAMAzUKl+/tbh2cAAAAASUVORK5CYII='); cursor: pointer; width: 64px; background-size: cover; height: 64px; } .badge { border-radius: 3px; border: none; cursor: pointer; display: inline-block; min-width: 10px; padding: 3px 7px; font-size: 12px; font-weight: 700; color: #fff; line-height: 1; vertical-align: baseline; white-space: nowrap; text-align: center; background-color: #999; border-radius: 10px; &.tcin { margin: 4px 0; } &.tcout { margin: 0 0 4px 0; } &.tcin, &.tcout { clear: both; float: left; border-radius: 3px; } } } &.on { background-color: #d8d8d8; .content { .ajs-progress .ajs-progress-bar { background-color: @mainColor; } } } &.on .info .badge.tcin, &.on .info .badge.tcout { background-color: @mainColor; cursor: pointer; } .content { overflow: hidden; zoom: 1; text-align: left; font-size: 14px; .heading { text-align: left; font-size: 14px; } .text { text-align: left; font-size: 14px; .word.on { font-weight: bold; } } .ajs-progress { border-radius: 3px; width: 100%; height: 2px; .ajs-progress-bar { background-color: #d8d8d8; height: 1px; } } } } } } ================================================ FILE: src/assets/less/plugin-timeline.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin time line */ @modulesSizeListNames: lg, md, sm, xs; @modulesSizeList: 110px, 80px, 60px, 25px; .ajs-plugin.plugin-timeline { position: relative; background-color: #000; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; .timeline-cursor { border-left: 1px solid @mainColor; display: block; height: 100%; width: 1px; left: 0%; position: absolute; z-index: 100; bottom: 30px; } .timeline-progress-container { position: absolute; width: 100%; height: 102px; background-color: @mainBackgroundColor; z-index: 90; right: 100%; } .timeaxis { /* tools bar */ .toolsbar { background-color: #3f3f3f; padding: 5px 10px 0 10px; height: 40px; .ajs-row { .ajs-col { float: left; position: relative; min-height: 1px; padding: 0px; margin: 0px; &:after { clear: both; } } .leftContainer { width: 16.66666667%; text-align: left; } .middleContainer { width: 66.66666667%; text-align: center; } .rightContainer { width: 16.66666667%; text-align: right; } } button.ajs-icon { display: inline-block; color: white; background-color: #333; border-radius: 50%; border: none; box-shadow: none; padding: px; width: 30px; height: 30px; padding: 0 2px 0 1px; line-height: 36px; font-size: 20px; &:hover { background-color: @mainColor; } } } /**Module TimeAxe**/ .module-timeaxis { position: relative; background-color: #333; height: 100px; margin-top: 2px; .line { height: 20px; position: absolute; top: 30px; width: 100%; margin-top: 5px; z-index: 99; border-bottom: 1px solid white; } .line-content { text-align: center; position: absolute; top: 50%; width: 100%; height: auto; z-index: 99; } .time-grid { height: 10px; width: 1px; padding-top: 2px; display: block; position: absolute; border-right: 1px solid #FFF; } .time-grid span.time { display: block; width: 55px; font-size: 12px; position: relative; top: -20px; line-height: 15px; left: 50%; margin-left: -27px; cursor: pointer; } } .timeaxis-label { display: none; } .toolbar-container { position: absolute; top: 0; right: 20px; .plugin-btn { border: none; box-shadow: none; background: none; color: #6c6c6c; font-size: 17px; line-height: 25px; } } &.off { height: 25px; background-color: #333; .toolsbar { display: none; } .module-timeaxis { display: none; } .timeaxis-label { position: absolute; top: 0; display: block; .label { font-size: 11px; padding: 0px 0px 0px 5px; margin: 0; } } } } /**Composants du timeline**/ .components { display: block; position: relative; width: 100%; overflow: hidden; .cuepoints-component, .segments-component, .images-component, .histogram-component, .visual-component { position: relative; cursor: pointer; } .cuepoints-component .module-cuepoints, .segments-component .module-segments, .images-component .module-images, .histogram-component .module-histogram, .visual-component .module-visual { position: relative; background-color: #333; height: 100px; margin-top: 2px; text-align: left; } .cuepoints-component.activated .module-cuepoints, .segments-component.activated .module-segments, .images-component.activated .module-images, .histogram-component.activated .module-histogram, .visual-component.activated .module-visual { background-color: #3f3f3f; } .cuepoints-component .module-cuepoints .line-content, .segments-component .module-segments .line-content, .images-component .module-images .line-content, .visual-component .module-visual .line-content { position: absolute; top: 50%; width: 100%; height: auto; z-index: 99; } .generate-theme(4); .generate-theme(@n, @i: 1) when (@i =< @n) { @sizeName: extract(@modulesSizeListNames, @i); .component.cuepoints-component.@{sizeName} .module-cuepoints, .component.segments-component.@{sizeName} .module-segments, .component.images-component.@{sizeName} .module-images, .component.histogram-component.@{sizeName} .module-histogram, .component.visual-component.@{sizeName} .module-visual { height: extract(@modulesSizeList, @i); } .@{sizeName} .focus-container { .ui-resizable-handle { height: extract(@modulesSizeList, @i); } } .generate-theme(@n, (@i + 1)); } @sizeName: extract(@modulesSizeListNames, 4); .cuepoints-component.@{sizeName} .module-cuepoints .line-content, .segments-component.@{sizeName} .module-segments .line-content, .images-component.@{sizeName} .module-images .line-content, .histogram-component.@{sizeName} .module-histogram .line-content, .visual-component.@{sizeName} .module-visual .line-content { display: none; } .component.@{sizeName} .sub, .component.@{sizeName} .bottom-toolbar-container, .component.@{sizeName} .focus-container { display: none; } .cuepoints-component .module-cuepoints .line, .segments-component .module-segments .line, .images-component .module-images .line, .histogram-component .module-images .line, .visual-component .module-visual .line { background-color: #fff; height: 1px; position: absolute; z-index: 98; top: 2px; width: 100%; } .cuepoints-component .module-cuepoints .cuepoint { position: absolute; vertical-align: middle; cursor: pointer; font-size: 20px; line-height: 13px; z-index: 98; margin-left: -10px; &.selected { animation-name: ajs-bounce; -webkit-animation-name: ajs-bounce; animation-duration: 1.6s; -webkit-animation-duration: 1.6s; animation-timing-function: ease; -webkit-animation-timing-function: ease; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; } } .segments-component .module-segments .segment { position: absolute; height: 7px; width: 1px; float: left; z-index: 99; background-color: @mainColor; cursor: pointer; border: none; margin: 0; padding: 0; .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } .ui-resizable-handle { position: absolute; font-size: .1px; z-index: 99999; display: block; } &.selected { /**hatch**/ animation-name: ajs-pulse; -webkit-animation-name: ajs-pulse; animation-duration: 2s; -webkit-animation-duration: 2s; animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; visibility: visible !important; } &.marker { height: 2px; margin: 0px; padding: 0px; top: 2px; .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: -3px; height: 8px; background-color: inherit; } .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: -3px; height: 8px; background-color: inherit; } } } .visual-component .module-visual { .cuepoint { position: absolute; vertical-align: middle; cursor: pointer; font-size: 20px; line-height: 13px; z-index: 98; margin-left: -10px; top: -2px; &.selected { animation-name: ajs-bounce; -webkit-animation-name: ajs-bounce; animation-duration: 1.6s; -webkit-animation-duration: 1.6s; animation-timing-function: ease; -webkit-animation-timing-function: ease; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; } } .segment { position: absolute; height: 7px; width: 1px; float: left; z-index: 99; background-color: @mainColor; cursor: pointer; .cuepoint { top: -7px; margin-right: -10px; } &.selected { /**hatch**/ animation-name: ajs-hatch; -webkit-animation-name: ajs-hatch; animation-duration: 2s; -webkit-animation-duration: 2s; animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; visibility: visible !important; } &.marker { height: 2px; margin: 0px; padding: 0px; top: 2px; .ui-resizable-w { cursor: w-resize; width: 15px; left: 0px; top: -6px; height: 15px; background-color: inherit; position: absolute; } .ui-resizable-e { cursor: e-resize; width: 15px; right: 0px; top: -6px; height: 15px; background-color: inherit; position: absolute; } } } } .images-component .module-images .image { position: absolute; float: left; z-index: 99; background-color: none; height: 50px; top: -25px; background-repeat: no-repeat; line-height: 50px; cursor: pointer; &.on { z-index: 100; .content { } &.segment { z-index: 100; border: solid 1px @mainColor; margin-top: -1px; .content { /*height: 45px;*/ } } } .content { height: 30px; z-index: 1; position: absolute; top: 15px; } hr.flow { border-color: #FFF; color: #FFF; display: block; margin: 0; padding: 0; position: relative; height: 0px; top: 28px; z-index: 0; border-style: double; border-width: 1px; width: 100%; &:after, &:before { display: inline-block; font-family: FontAwesome; font-size: 1.1em; position: absolute; top: -25px; } &:after { right: -6px; content: "\f111"; } &:before { left: -3px; content: "\f142"; } } } .histogram-component .module-histogram .cuepoint { position: absolute; vertical-align: middle; cursor: pointer; font-size: 16px; line-height: 8px; z-index: 98; margin-left: -5px; } .histogram-component .module-histogram .label { display: block; position: absolute; top: 0px; } .histogram-component .module-histogram .line-content { position: relative; height: 100%; } .cuepoints-component .module-cuepoints .label, .segments-component .module-segments .label, .images-component .module-images .label, .histogram-component .module-histogram .label, .visual-component .module-visual .label { background-color: transparent; -webkit-touch-callout: text; -webkit-user-select: text; -khtml-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; padding: 0px 0px 0px 5px; margin: 0; display: inline-block; } .cuepoints-component .module-cuepoints .callback, .segments-component .module-segments .callback, .images-component .module-images .callback, .histogram-component .module-histogram .callback, .visual-component .module-visual .callback { background-color: transparent; -webkit-touch-callout: text; -webkit-user-select: text; -khtml-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; padding: 0px 0px 0px 5px; margin: 0; display: inline-block; } .sub.cuepoints-component .module-cuepoints, .sub.segments-component .module-segments, .sub.images-component .module-images, .sub.images-histogram .module-histogram, .sub.visual-histogram .module-visual { background-color: rgba(100, 100, 100, 0.68); } .focus-container { left: 0%; width: 222px; display: block; background-color: rgba(100, 100, 100, 0.68); height: 50%; border: 0px solid #333; box-shadow: none; position: absolute; top: 0px; display: block; z-index: 100; min-width: 41px; &.zoom { background-color: @mainBackgroundColor; height: 100%; } .ui-resizable-handle { background-color: #6c6c6c; width: 20px; height: 100%; text-align: center; vertical-align: middle; display: inline-block; margin-left: 0px; margin-right: 0px; &.ui-resizable-w { float: left; font-size: 20px; position: relative; &:before { -webkit-transform: translateX(-50%) translateY(-50%) rotate(-90deg); -ms-transform: translateX(-50%) translateY(-50%) rotate(-90deg); transform: translateX(-50%) translateY(-50%) rotate(-90deg); display: block; width: 20px; height: 20px; margin: 2px 0px 0px 12px; padding: 0px; position: absolute; top: 50%; } } &.ui-resizable-e { float: right; font-size: 20px; &:before { -webkit-transform: translateX(-50%) translateY(-50%) rotate(-90deg); -ms-transform: translateX(-50%) translateY(-50%) rotate(-90deg); transform: translateX(-50%) translateY(-50%) rotate(-90deg); display: block; width: 20px; height: 20px; margin: 2px 0px 0px 12px; padding: 0px; position: absolute; top: 50%; } } } } .bottom-toolbar-container { position: absolute; bottom: 5px; left: 5px; display: block; .focus-btn { background-color: transparent; border: none; color: white; font-size: 20px; line-height: 20px; } } .component.focus-off { .focus-container { display: none; } .bottom-toolbar-container { display: block; } .sub { display: none; } } .component.focus-on { .focus-container { display: block; } .bottom-toolbar-container { display: none; } .sub { display: block; } } @smallSizeName: extract(@modulesSizeListNames, 4); .component.@{smallSizeName} .sub, .component.@{smallSizeName} .bottom-toolbar-container, .component.@{smallSizeName} .focus-container { display: none; } .timecursor { left: 0%; position: absolute; top: 0px; width: 1px; border-left: 1px solid @mainColor; height: 100%; } .toolbar-container { position: absolute; top: 0; right: 20px; .plugin-btn { border: none; box-shadow: none; background: none; color: #6c6c6c; font-size: 17px; line-height: 25px; } .close-btn, .sort-btn, .expand-btn { color: @BtToolContColor; height: 28px; line-height: 28px; text-align: center; width: 28px; cursor: pointer; border: none; background: transparent; font-size: 20px; } .nav-controls { color: @BtToolContColor; display: inline-block; float: left; line-height: 28px; margin-right: 15px; text-align: center; vertical-align: middle; font-size: 20px; padding: 0; .prev-control { cursor: pointer; border: none; background: transparent; color: @BtToolContColor; font-size: 20px; padding: 0; } .next-control { cursor: pointer; border: none; background: transparent; color: @BtToolContColor; font-size: 20px; padding: 0; } } } } /**Bar de controle**/ .module-nav-bar-container { .info { padding-left: 15px; line-height: 30px; } .toolsbar { height: 30px; padding: 0px; background-color: #3f3f3f; button.ajs-icon { border-radius: 0%; width: 30px; line-height: 25px; border: none; background-color: transparent; color: white; } } .leftContainer { text-align: left; border: none; background-color: transparent; float: left; width: 16.66666667%; } .middleContainer { text-align: center; border: none; background-color: transparent; float: left; width: 66.66666667%; } .rightContainer { text-align: right; border: none; background-color: transparent; float: right; width: 16.66666667%; .config-menu { padding-right: 30px; .config-btn { width: 30px; line-height: 29px; cursor: pointer; font-size: 2.4em; } } .config-menu-list { background: #FFF; border: none; box-shadow: none; margin: 0px; position: absolute; bottom: 30px; border-radius: 0px; right: 1px; width: 200px; list-style: none; padding: 5px 0px 5px 5px; li { padding-left: 5px; color: #000; cursor: pointer; text-align: left; } } } &:after { clear: both; } } /**resizeable component**/ .ui-resizable-s { display: block; height: 30px; width: 30px; font-size: 30px; position: absolute; left: 100%; bottom: 0; margin-left: -45px; padding-left: 15px; display: inline-block; vertical-align: middle; line-height: 40px; font-weight: normal; font-style: normal; cursor: s-resize; } } ================================================ FILE: src/assets/less/plugin-watermark.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.plugin-watermark { display: block; color: #FFF; position: absolute; width: 100%; height: 100%; z-index: 98; top: 0; .watermark { background-color: transparent; background-repeat: no-repeat; position: absolute; } } ================================================ FILE: src/assets/less/plugin.less ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin */ .ajs-plugin { font-family: @fontMain; color: #FFF; clear: both; overflow: hidden; font-size: 11px; .error { text-align: center; } .loader { text-align: center; width: 100%; top: 50%; font-size: 3em; } /* Custom de la scrollbar */ &::-webkit-scrollbar, & ::-webkit-scrollbar { width: 10px; } &::-webkit-scrollbar-thumb, & ::-webkit-scrollbar-thumb { background: rgba(108, 108, 108, .6); } } @import "player-custom-control-bar"; @import "plugin-timeline"; @import "plugin-text-sync"; @import "plugin-captions"; @import "plugin-overlay"; @import "plugin-watermark"; @import "plugin-menu-contextuel"; @import "plugin-editor"; @import "plugin-selected-item-editor"; @import "plugin-storyboard"; ================================================ FILE: src/assets/sass/_ajs-animations.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ @keyframes ajs-hatch { 0% { transform: rotate(0deg) scaleY(0.6); } 20% { transform: rotate(-2deg) scaleY(1.05); } 35% { transform: rotate(2deg) scaleY(1); } 50% { transform: rotate(-2deg); } 65% { transform: rotate(1deg); } 80% { transform: rotate(-1deg); } 100% { transform: rotate(0deg); } } @webkit-keyframes ajs-hatch { 0% { -webkit-transform: rotate(0deg) scaleY(0.6); } 20% { -webkit-transform: rotate(-2deg) scaleY(1.05); } 35% { -webkit-transform: rotate(2deg) scaleY(1); } 50% { -webkit-transform: rotate(-2deg); } 65% { -webkit-transform: rotate(1deg); } 80% { -webkit-transform: rotate(-1deg); } 100% { -webkit-transform: rotate(0deg); } } @keyframes ajs-bounce { 0% { transform: translateY(0%) scaleY(0.6); } 60% { transform: translateY(-100%) scaleY(1.1); } 70% { transform: translateY(0%) scaleY(0.95) scaleX(1.05); } 80% { transform: translateY(0%) scaleY(1.05) scaleX(1); } 90% { transform: translateY(0%) scaleY(0.95) scaleX(1); } 100% { transform: translateY(0%) scaleY(1) scaleX(1); } } @webkit-keyframes ajs-bounce { 0% { -webkit-transform: translateY(0%) scaleY(0.6); } 60% { -webkit-transform: translateY(-100%) scaleY(1.1); } 70% { -webkit-transform: translateY(0%) scaleY(0.95) scaleX(1.05); } 80% { -webkit-transform: translateY(0%) scaleY(1.05) scaleX(1); } 90% { -webkit-transform: translateY(0%) scaleY(0.95) scaleX(1); } 100% { -webkit-transform: translateY(0%) scaleY(1) scaleX(1); } } @keyframes ajs-pulse { 0% { transform: scale(0.9); opacity: 0.7; } 50% { transform: scale(1); opacity: 1; } 100% { transform: scale(0.9); opacity: 0.7; } } @webkit-keyframes ajs-pulse { 0% { -webkit-transform: scale(0.95); opacity: 0.7; } 50% { -webkit-transform: scale(1); opacity: 1; } 100% { -webkit-transform: scale(0.95); opacity: 0.7; } } // spinner @keyframes ajs-spinner { to {transform: rotate(360deg);} } @webkit-keyframes ajs-spinner { to {-webkit-transform: rotate(360deg);} } ================================================ FILE: src/assets/sass/_ajs-mixins.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin custom control bar */ // Mixins : transiition /** * global animation * $properties transition * $param : Time duration (s), function */ @mixin transition($property:all, $time-duration:1s, $function-style:ease-out) { -webkit-transition: $property $time-duration $function-style; -moz-transition: $property $time-duration $function-style; -ms-transition: $property $time-duration $function-style; -o-transition: $property $time-duration $function-style; transition: $property $time-duration $function-style; } // Transformation @mixin transform-scale($scale:1.5) { -webkit-transform: scale($scale); -ms-transform: scale($scale); transform: scale($scale); transform: scale($scale); } ================================================ FILE: src/assets/sass/_ajs-webfont.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ @font-face { font-family:"ajs-webfont"; src:url("../fonts/ajs-webfont.eot?da2b33fb7481b6e5ffca9457ecddfd8e"); font-weight:normal; font-style:normal; } @font-face { font-family:"ajs-webfont"; src:url("../fonts/ajs-webfont.eot?da2b33fb7481b6e5ffca9457ecddfd8e"); src:url("../fonts/ajs-webfont.eot?#iefix") format("embedded-opentype"), url("data:application/x-font-woff;charset=utf-8;base64,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") format("woff"), url("../fonts/ajs-webfont.ttf?da2b33fb7481b6e5ffca9457ecddfd8e") format("truetype"); font-weight:normal; font-style:normal; } .ajs-icon { font-family:"ajs-webfont"; display:inline-block; vertical-align:middle; line-height:1; font-weight:normal; font-style:normal; speak:none; text-decoration:inherit; text-transform:none; text-rendering:auto; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; } // Icons .ajs-icon-account:before { content:"\f101"; } .ajs-icon-add-whole-segment:before { content:"\f102"; } .ajs-icon-amalia-js:before { content:"\f103"; } .ajs-icon-arrows-h:before { content:"\f104"; } .ajs-icon-arrows-v:before { content:"\f105"; } .ajs-icon-bell:before { content:"\f106"; } .ajs-icon-building:before { content:"\f107"; } .ajs-icon-caret-right:before { content:"\f108"; } .ajs-icon-cercle:before { content:"\f109"; } .ajs-icon-check:before { content:"\f10a"; } .ajs-icon-chevron-circle-down:before { content:"\f10b"; } .ajs-icon-chevron-circle-left:before { content:"\f10c"; } .ajs-icon-chevron-circle-right:before { content:"\f10d"; } .ajs-icon-chevron-circle-up:before { content:"\f10e"; } .ajs-icon-chevron-down:before { content:"\f10f"; } .ajs-icon-chevron-left:before { content:"\f110"; } .ajs-icon-chevron-right:before { content:"\f111"; } .ajs-icon-chevron-up:before { content:"\f112"; } .ajs-icon-chromecast-active:before { content:"\f113"; } .ajs-icon-chromecast:before { content:"\f114"; } .ajs-icon-circle:before { content:"\f115"; } .ajs-icon-cog:before { content:"\f116"; } .ajs-icon-cogs:before { content:"\f117"; } .ajs-icon-comment:before { content:"\f118"; } .ajs-icon-compress:before { content:"\f119"; } .ajs-icon-control-backward:before { content:"\f11a"; } .ajs-icon-control-fast-forward:before { content:"\f11b"; } .ajs-icon-control-fast-rewind:before { content:"\f11c"; } .ajs-icon-control-forward:before { content:"\f11d"; } .ajs-icon-control-pause:before { content:"\f11e"; } .ajs-icon-control-play:before { content:"\f11f"; } .ajs-icon-control-rewind:before { content:"\f120"; } .ajs-icon-controlbar-compress:before { content:"\f121"; } .ajs-icon-controlbar-fullscreen:before { content:"\f122"; } .ajs-icon-controlbar-pause:before { content:"\f123"; } .ajs-icon-controlbar-play:before { content:"\f124"; } .ajs-icon-controlbar-settings:before { content:"\f125"; } .ajs-icon-controlbar-volume-left-off:before { content:"\f126"; } .ajs-icon-controlbar-volume-left:before { content:"\f127"; } .ajs-icon-controlbar-volume-min:before { content:"\f128"; } .ajs-icon-controlbar-volume-off:before { content:"\f129"; } .ajs-icon-controlbar-volume-right-off:before { content:"\f12a"; } .ajs-icon-controlbar-volume-right:before { content:"\f12b"; } .ajs-icon-controlbar-volume_max:before { content:"\f12c"; } .ajs-icon-controlbar-volume_middle:before { content:"\f12d"; } .ajs-icon-download:before { content:"\f12e"; } .ajs-icon-eject:before { content:"\f12f"; } .ajs-icon-ellipsis-h:before { content:"\f130"; } .ajs-icon-ellipsis-v:before { content:"\f131"; } .ajs-icon-eraser:before { content:"\f132"; } .ajs-icon-expand:before { content:"\f133"; } .ajs-icon-eye-off:before { content:"\f134"; } .ajs-icon-eye-on:before { content:"\f135"; } .ajs-icon-facetime:before { content:"\f136"; } .ajs-icon-female:before { content:"\f137"; } .ajs-icon-github:before { content:"\f138"; } .ajs-icon-information:before { content:"\f139"; } .ajs-icon-jogs-backward-0x:before { content:"\f13a"; } .ajs-icon-jogs-backward-1x:before { content:"\f13b"; } .ajs-icon-jogs-backward-2x:before { content:"\f13c"; } .ajs-icon-jogs-backward-3x:before { content:"\f13d"; } .ajs-icon-jogs-backward-4x:before { content:"\f13e"; } .ajs-icon-jogs-center:before { content:"\f13f"; } .ajs-icon-jogs-fast-backward:before { content:"\f140"; } .ajs-icon-jogs-fast-forward:before { content:"\f141"; } .ajs-icon-jogs-forward-0x:before { content:"\f142"; } .ajs-icon-jogs-forward-1x:before { content:"\f143"; } .ajs-icon-jogs-forward-2x:before { content:"\f144"; } .ajs-icon-jogs-forward-3x:before { content:"\f145"; } .ajs-icon-jogs-forward-4x:before { content:"\f146"; } .ajs-icon-key:before { content:"\f147"; } .ajs-icon-legal:before { content:"\f148"; } .ajs-icon-list-close:before { content:"\f149"; } .ajs-icon-list-open:before { content:"\f14a"; } .ajs-icon-lock-close:before { content:"\f14b"; } .ajs-icon-lock-open:before { content:"\f14c"; } .ajs-icon-male:before { content:"\f14d"; } .ajs-icon-microphone-off:before { content:"\f14e"; } .ajs-icon-microphone-on:before { content:"\f14f"; } .ajs-icon-minus:before { content:"\f150"; } .ajs-icon-music:before { content:"\f151"; } .ajs-icon-picture:before { content:"\f152"; } .ajs-icon-plus:before { content:"\f153"; } .ajs-icon-power:before { content:"\f154"; } .ajs-icon-refresh:before { content:"\f155"; } .ajs-icon-remove:before { content:"\f156"; } .ajs-icon-reorder:before { content:"\f157"; } .ajs-icon-screenshot:before { content:"\f158"; } .ajs-icon-scrubber-cursor:before { content:"\f159"; } .ajs-icon-search:before { content:"\f15a"; } .ajs-icon-sign-in:before { content:"\f15b"; } .ajs-icon-sign-out:before { content:"\f15c"; } .ajs-icon-sort:before { content:"\f15d"; } .ajs-icon-sound-link-off:before { content:"\f15e"; } .ajs-icon-sound-link-on:before { content:"\f15f"; } .ajs-icon-stop:before { content:"\f160"; } .ajs-icon-transcription:before { content:"\f161"; } .ajs-icon-volume-down:before { content:"\f162"; } .ajs-icon-volume-off:before { content:"\f163"; } .ajs-icon-volume-up:before { content:"\f164"; } .ajs-icon-zoom-in:before { content:"\f165"; } .ajs-icon-zoom-out:before { content:"\f166"; } ================================================ FILE: src/assets/sass/_default-style.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-tooltip { font-family: Arial, Helvetica, sans-serif; color: #fff; background: #0cf; padding: 10px 5px 10px 5px; max-width: 300px; box-shadow: none; border: none; margin-top: -50px; &:after { content: ""; position: absolute; left: 50%; top: -20px; width: 15px; height: 15px; box-shadow: none; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); tranform: rotate(45deg); border: none; background: #0cf; margin-left: -7.5px; } } .ui-tooltip { padding: 8px; position: absolute; z-index: 9999; max-width: 300px; -webkit-box-shadow: 0 0 5px #aaa; box-shadow: 0 0 5px #aaa; } .ui-helper-hidden-accessible { display: none; } .ui-selectable-helper { position: absolute; z-index: 100; border: 1px dotted #eaeaea; } ================================================ FILE: src/assets/sass/_player-custom-control-bar.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin custom control bar */ // Add option control layer on display .ajs-control-layer { .ajs-icon { position: absolute; width: 100%; top: 50%; text-align: center; z-index: 9999; margin-top: -80px; &.ajs-icon-controlbar-play, &.ajs-icon-controlbar-pause { color: white; font-size: 90px; opacity: .5; @include transform-scale(1); @include transition(all, 0.5s, ease-out); } } // Transformation with scale up &.scale-up { .ajs-icon-controlbar-play, .ajs-icon-controlbar-pause { @include transform-scale(2); @include transition(all, 0.5s, ease-out); } } } .ajs { .plugin-custom-controlbar { width: 100%; background-color: #1d1d1d; background-image: -webkit-gradient(linear, 100% 0, 0 100%, from(#232323), to(#1d1d1d)); background-image: -webkit-linear-gradient(top, #232323 0%, #1d1d1d 100%); background-image: -moz-linear-gradient(top, #232323 0%, #1d1d1d 100%); background-image: -o-linear-gradient(top, #232323 0%, #1d1d1d 100%); background-image: linear-gradient(#232323, #1d1d1d); overflow: visible; margin: 0; padding: 0; z-index: 900; opacity: .9; position: relative; .ajs-time-indicator { bottom: 25px; position: absolute; width: 50px; height: 20px; border: none; background-color: rgba(108, 108, 108, .5); left: 50%; margin-left: -25px; font-size: 9px; line-height: 20px; text-align: center; display: none; border-radius: 5px; padding: 0px 5px 0px 5px; z-index: 1000; .ajs-tooltip-text { font-size: 9px; line-height: 20px; text-align: center; color: white; } } .ajs-row { margin: 0; .ajs-container { display: block; float: left; width: 33.33333333%; min-height: 70px; height: 70px; position: relative; padding: 0; margin: 0; z-index: 0; &.left-container { } &.middle-container { text-align: center; } &.right-container { } } } .player { top: 0; } .player-base-button { background: none; margin: 0 auto; text-align: center; width: 35px; color: #fff; display: inline-block; cursor: pointer; // Prev and Next base button .ajs-icon-control-fast-rewind, .ajs-icon-control-fast-forward { font-size: 1.5em; position: relative; top: 15px; } } .player-play-button, .player-pause-button { background: none; cursor: pointer; display: inline-block; line-height: 0; margin: 0 auto; position: relative; text-align: center; width: 35px; color: #fff; font-size: 35px; position: relative; top: 18px; &.on { display: inline-block; } &.off { display: none; } span.button-container { position: relative; } } .player-label { display: inline-block; width: 160px; line-height: 30px; margin-left: 3px; margin-right: 3px; height: 28px; background: none; } .player-timelabel.time-display { display: inline-block; line-height: 18px; padding-left: 15px; height: 35px; position: relative; top: 26px; min-width: 80px; .time-current { color: white; display: inline-block; font-size: 1.2em; } .time-separator { color: white; display: inline-block; padding-left: 5px; padding-right: 5px; position: relative; font-size: 1.2em; top: 0; &:before { content: "/"; } } .time-duration { color: white; display: inline-block; font-size: 1.2em; position: relative; top: 0; } // Disabled TC &.off { .time-separator { display: none; } } } .player-fullscreen-button { width: 35px; color: #fff; margin: 15px 0 0 20px; cursor: pointer; margin-right: 10px; font-size: 35px; position: absolute; right: 0; } .player-volume-control { vertical-align: middle; font-size: 2em; margin-right: 20px; position: relative; top: -6px; height: 35px; width: 50px; padding-top: 0; cursor: pointer; float: right; line-height: 35px; canvas { display: none; } .volume-control-btn { top: 16px; margin: 0; padding: 0; display: inline-block; position: relative; vertical-align: middle; line-height: 35px; width: 50px; height: 35px; right: 60px; font-size: 1.4em; text-align: center; color: white; span.ajs-icon { position: absolute; z-index: 90; display: block; line-height: 50px; text-align: left; width: inherit; height: 35px; vertical-align: middle; text-align: left; } span.ajs-icon.ajs-icon-volume-on:before, span.ajs-icon.ajs-icon-volume-off:before, span.ajs-icon.ajs-icon-volume-up:before, span.ajs-icon.ajs-icon-volume-down:before { display: block; width: 50px; height: inherit; text-align: left; } span.ajs-icon.ajs-icon-volume-off:before { margin-left: -7px; } span.ajs-icon.ajs-icon-volume-up:before { margin-left: 0; } span.ajs-icon.ajs-icon-volume-down:before { margin-left: -4px; } /* Slider container : control volume using ui-handler */ .volume-slider-ctn { display: block; position: absolute; z-index: 100; background-color: $primaryBackgroundColor; width: 70px; height: 190px; bottom: -70px; margin-left: -15px; &.on { opacity: 1; bottom: -20px; @include transition(all, 0.5s, ease-out); } &.off { opacity: 0; bottom: -250px; @include transition(all, 0.5s, ease-out); } .slider-volume { // Background progress volume &.ui-slider { position: relative; border: none; border-radius: 0; margin: 0 20px; } .ui-slider-range { background: none; background-color: $mainColor; background-position: 0% 0%; border-bottom-color: rgb(51, 51, 51); border-radius: none; bottom: 0; color: rgb(51, 51, 51); height: 140px; left: 0; line-height: 30px; position: absolute; text-align: left; width: 5px; z-index: 1; } &.ui-slider-vertical { background-color: $primaryBackgroundColor; height: 140px; top: 25px; width: 5px; left: 10px; } &.ui-widget-content { background: none; background-color: black; border: none; margin-left: 20px; outline: none; } .ui-slider-handle.ui-state-default.ui-corner-all { position: absolute; z-index: 2; border: solid 1px lighten($secondaryBackgroundColor, 50%); background: none; background-color: $secondaryBackgroundColor; background-repeat: no-repeat; box-shadow: none; border-radius: 50px; cursor: pointer; display: block; height: 15px; width: 16px; left: -5px; right: 25px; margin-bottom: -8px; outline: none; filter: none; } } } } } //Media queries on element only .xs .player-volume-control { display: none; } .player-progress-bar { height: 10px; margin-bottom: 0; overflow: hidden; background-color: #6a6969; border-radius: 0; clear: both; position: relative; text-align: left; color: #404040; z-index: 50; .buffer-bar { display: block; height: 100%; background-color: #555; position: relative; top: 0; box-sizing: border-box; width: 0; } .ui-slider-range { float: left; width: 0; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; background-color: #58c8b0; position: absolute; z-index: 1; display: block; border: 0; background-position: 0 0; } .ui-slider-handle { background-color: #fff; border-radius: 0%; cursor: pointer; float: right; height: 10px; right: 0; width: 10px; z-index: 2; text-shadow: none; margin-left: -.6em; position: absolute; background-repeat: no-repeat; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); color: #333; font-size: 13px; line-height: normal; border: 1px solid #ccc; border-bottom-color: #bbb; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -webkit-transition: 0.1s linear background-image; -moz-transition: 0.1s linear background-image; -ms-transition: 0.1s linear background-image; -o-transition: 0.1s linear background-image; transition: 0.1s linear background-image; overflow: visible; top: -2px; } &.ui-slider .ui-slider-range { background: $mainGradient; float: left; width: 0; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; left: 0; top: 0; position: absolute; z-index: 1; display: block; border: 0; background-position: 0 0; color: #ffffff; background-color: #0064cd; background-repeat: repeat-x; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0;; border-color: #0064cd #0064cd #003f81; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); } &.ui-widget-content { background: #6c6c6c; border: none; outline: none; } } .player-channel-volume-control-position { display: none; position: relative; width: 125px; margin: 0 auto; @media (min-width: $screen-md-min) { display: block; } .player-channel-volume-control { padding-top: 0; cursor: pointer; height: 35px; width: 35px; line-height: 30px; color: #fff; .volume-control-btn { vertical-align: middle; padding-top: 15px; top: 0; margin-left: 54px; margin-top: 8px; height: 35px; line-height: 30px; display: block; font-size: 40px; } // Channel 2 canal volume .channel-volume-sliders { position: absolute; bottom: -252px; padding-left: 0; height: 225px; background-repeat: no-repeat; left: 24px; display: block; background: linear-gradient(90deg, $backgroundColor 50%, $secondaryBackgroundColor 50%); opacity: 0; @include transition(all, 0.5s, ease-in); &.on { bottom: -28px; display: block; opacity: 1; @include transition(all, 0.5s, ease-out); } .channel-volume-info { display: block; position: relative; padding-left: 5px; top: 2px; .channel-volume-info-left, .channel-volume-info-right { width: 38px; height: 40px; color: #fff; float: left; text-align: center; margin-left: 0; font-size: 25px; padding-left: 2px; position: relative; top: 8px; } .channel-volume-info-left { text-align: left; } .channel-volume-info-right { text-align: center; } .channel-volume-info-mid { width: 12px; height: 40px; color: #fff; float: left; text-align: center; padding-top: 10px; left: 30px; margin-left: 0; .unify { color: #EEE; font-size: 23px; font-weight: bold; position: relative; left: -8px; &.on { color: cadetblue; } // Adjust position unlink &.ajs-icon-sound-link-on { top: 6px; } &.ajs-icon-sound-link-off { top: 3px; } } } } .channel-volume-control { display: block; margin: 0; top: 10px; position: relative; .channel-volume-control-left, .channel-volume-control-right { height: 145px; color: #fff; float: left; width: 30px; margin-left: 19px; .ui-state-focus, .ui-state-hover { } .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 16px; height: 16px; cursor: default; -ms-touch-action: none; touch-action: none; border-radius: 100%; } // Cursor volume .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid lighten($secondaryBackgroundColor, 45%); background: none; background: $mainBackgroundColor; font-weight: normal; color: #454545; cursor: pointer; outline: none; } .ui-slider-vertical { width: 4px; height: 140px; } // Progress volume .ui-widget-content { border: 2px solid lighten(black, 10%); background: none; background-color: lighten(black, 15%); cursor: pointer; outline: none; position: relative; } .ui-slider-vertical .ui-slider-handle { left: -8px; margin-left: 0; margin-bottom: -.6em; } } .channel-volume-control-mid { width: 35px; height: 3px; background-color: $secondaryColor; clear: both; cursor: default; background-repeat: no-repeat; margin-left: 5px; position: absolute; visibility: hidden; left: 24px; top: 39px; &.on { visibility: visible; top: 39px; } } } } } } .player-jog-shuttle-button { line-height: 30px; color: #fff; display: inline-block; width: 240px; position: relative; border: 1px solid #cacaca; border-radius: 20px; height: 38px; top: 18px; margin: 0 30px 0 30px; @media(min-width: 50px) and (max-width: 1058px) { display: none; } span.button-container { border: none; border-radius: 0%; display: inline-block; height: 32px; line-height: 40px; font-size: 35px; width: 100%; position: relative; top: 2px; .jog-shuttle-separator { display: inline-block; width: 2px; background-color: #eee; height: 32px; position: absolute; right: 50%; } .backward-container, .forward-container { height: 32px; display: inline-block; line-height: 30px; float: none; color: rgba(238, 238, 238, 0.25); margin-top: 5px; padding-right: 5px; padding-left: 5px; span { height: 32px; padding-left: 10px; padding-right: 10px; position: absolute; color: #66cc99; top: 100px; &.ajs-icon-jogs-forward-0x, &.ajs-icon-jogs-backward-0x { visibility: hidden; } &.ajs-icon-jogs-backward-1x, &.ajs-icon-jogs-backward-2x, &.ajs-icon-jogs-backward-3x, &.ajs-icon-jogs-backward-4x, &.ajs-icon-jogs-fast-backward { left: 0; } &.ajs-icon-jogs-forward-1x, &.ajs-icon-jogs-forward-2x, &.ajs-icon-jogs-forward-3x, &.ajs-icon-jogs-forward-4x, &.ajs-icon-jogs-fast-forward { color: #66cc99; right: -5px; top: 2px; } &.ajs-icon-jogs-backward-1x, &.ajs-icon-jogs-backward-2x, &.ajs-icon-jogs-backward-3x, &.ajs-icon-jogs-backward-4x, &.ajs-icon-jogs-fast-backward { color: #66cc99; left: -5px; top: 2px; } } } .backward-container { float: left; text-align: left; border: none; width: 74px; } .forward-container { float: right; text-align: right; width: 74px; } .jog-shuttle { background-color: transparent; border-radius: 20px; position: absolute; width: 151px; top: 0; height: 32px; margin-left: 43px; -webkit-transition: opacity 0.5s ease-in; -moz-transition: opacity 0.5s ease-in; -o-transition: opacity 0.5s ease-in; -ms-transition: opacity 0.5s ease-in; transition: opacity 0.5s ease-in; display: block; border: none; &.on { display: block; } span.ui-slider-handle { border: 1px solid; top: -8px; margin: 0; position: absolute; z-index: 2; cursor: pointer; padding: 0; border-radius: 100%; background-color: #1D1D1D; height: 48px; width: 50px; line-height: 30px; margin-left: -25px; font-size: 48px; color: #eee; font-weight: normal; outline: none; } } } } } //Media queries for extra extra small <=320px container element only &.xxs { // Time display .player-timelabel.time-display { display: inline-block; line-height: 18px; padding-left: 15px; height: 35px; position: relative; top: 18px; min-width: 80px; .time-current { display: block; font-size: 1.2em; } .time-separator { display: inline-block; font-size: 0.8em; } .time-duration { font-size: 0.8em; } } // Volume control .player-volume-control, .player-channel-volume-control-position { display: none; } } //Media queries for extra small container element only &.xs { // Time display .player-timelabel.time-display { display: inline-block; line-height: 18px; padding-left: 15px; height: 35px; position: relative; top: 18px; min-width: 80px; .time-current { display: block; font-size: 1.2em; } .time-separator { display: inline-block; font-size: 0.8em; } .time-duration { font-size: 0.8em; } } // Volume control .player-volume-control, .player-channel-volume-control-position { display: none; } // Jog Shuttle .player-jog-shuttle-button { display: none; } } //Media queries for small container element only &.sm { // Time display .player-timelabel.time-display { top: 18px; .time-current { display: block; font-size: 1.2em; } .time-separator { display: inline-block; font-size: 0.8em; } .time-duration { font-size: 0.8em; } .player-volume-control-position, .player-channel-volume-control { display: none; } } // Jog Shuttle .player-jog-shuttle-button { display: none; } // Volume position .player-channel-volume-control-position { margin-right: 40px; } } } ================================================ FILE: src/assets/sass/_player.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Player */ /** * Plugin control bar */ .ajs { overflow: hidden; font-family: $fontMain; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; line-height: 0px; .ajs-loader { color: white; position: absolute; z-index: 100; text-align: center; width: 100%; height: 100%; top: 50%; font-size: 100px; margin-top: -50px; .ajs-icon { $time-duration:800ms; animation: ajs-spinner $time-duration linear infinite; display: inline-block; -webkit-animation: ajs-spinner $time-duration linear infinite; transform-origin: 50% 50%; line-height: 104px; height: 70px; } } .ajs-error { position: absolute; z-index: 100; width: 100%; height: 100%; background-color: black; color: white; vertical-align: middle; text-align: center; line-height: 20px; top: 0; p { margin-left: auto; margin-right: auto; position: relative; top: 50%; margin-top: -25px; } } /* Reset background with font Awesome */ .ajs .ui-state-default .ui-icon[class*=" fa-"] { background: none; text-indent: 0; } } /**tooltip**/ .ui-tooltip { font-family: $fontMain; padding: 5px 5px; color: white; border: none; box-shadow: none; border: none; box-shadow: none; background: $mainColor; p { font-size: 14px; margin: 0; } .timeline-images-component { padding: 3px; &.tooltip-image { width: 200px; } } .image { max-width: 100%; } } .ajs-arrow { width: 70px; height: 16px; overflow: hidden; position: absolute; left: 50%; margin-left: -35px; bottom: -16px; border: none; &:after { content: ""; position: absolute; left: 20px; top: -20px; width: 25px; height: 25px; box-shadow: none; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); tranform: rotate(45deg); border: none; background: $mainColor; } &.top { top: -16px; bottom: auto; &:after { bottom: -20px; top: auto; } } &.left { left: 20%; } } .inalabplayer-ui-resizable-helper { z-index: 9999; border: 1px dashed #6c6c6c !important; } ================================================ FILE: src/assets/sass/_plugin-captions.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin caption */ .ajs-plugin.plugin-caption { display: block; color: #FFF; position: absolute; bottom: 100px; line-height: 20px; text-align: center; width: 100%; background-color: $inverseBackgroundColor; min-height: 20px; z-index: 98; padding-left: 0; padding-right: 0; font-size: 1.4em; &.fullScreenOn { font-size: 3em; line-height: 45px; } &.fullScreenOff { font-size: 1.4em; } } ================================================ FILE: src/assets/sass/_plugin-editor.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.editor { position: relative; .loader { position: absolute; top: 110px; z-index: 100; left: 0; right: 0; margin: 0; padding: 0; } /** * Plugin list editor */ &.plugin-list-editor { color: #666; .heading { height: 30px; border: none; line-height: 25px; background-color: #616161; color: #CCC; .title { text-align: left; padding-left: 10px; margin: 0; color: #FFF; line-height: 30px; font-size: 14px; } } .body { ul.listOfmetadata { box-sizing: border-box; color: #cacaca; display: block; font-size: 14px; line-height: 20px; list-style-type: disc; margin-bottom: 0px; margin-top: 0px; padding-left: 0px; height: 90px; overflow-y: overlay; li.item { position: relative; display: block; padding: 5px 15px; margin: 0; background-color: #eceff1; border: none; color: #000; font-size: 11px; &.selected { background-color: #546e7a; color: rgba(255, 255, 255, 0.87); } span.delete { float: right; padding: 0px; font-size: 10px; color: #fff; text-align: center; white-space: nowrap; background-color: #E57373; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 20px; width: 20px; margin: auto; position: relative; vertical-align: middle; box-shadow: none; line-height: 23px; margin-left: 5px; &:before { margin-left: -1px; } } span.duplicate { float: right; padding: 0px; font-size: 10px; color: #fff; text-align: center; white-space: nowrap; background-color: #3cf; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 20px; width: 20px; margin: auto; position: relative; vertical-align: middle; box-shadow: none; line-height: 23px; &:before { margin-left: -1px; } } } } } .footer { height: 25px; border: none; line-height: 25px; background-color: #616161; color: #CCC; text-align: center; .add-metadata { min-width: 10px; font-size: 25px; font-weight: normal; color: #fff; text-align: center; white-space: nowrap; background-color: #00CC99; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 35px; width: 35px; margin: auto; position: relative; vertical-align: middle; margin-top: -25px; box-shadow: none; line-height: 40px; text-align: left; &:before { margin-left: -1px; } } } } /** * Plugin block editor */ &.plugin-block-editor { color: #666; .heading { height: 30px; border: none; line-height: 25px; background-color: #616161; color: #CCC; .title { text-align: left; padding-left: 10px; margin: 0; color: #FFF; line-height: 30px; font-size: 14px; } } .body { padding: 5px 5px 15px 5px; form.formMetadataBlock { .form-item { padding: 0px; margin: 0px; box-shadow: none; font-size: 12px; .input { width: 100%; border: none; box-shadow: none; background-color: #eaeaea; color: #000; height: 25px; padding-left: 5px; border-radius: 0px; font-size: 12px; } .text-area { width: 100%; height: 50px; border-radius: 3px; border: 1px solid #ccc; display: inline-block; padding: 4px; font-size: 12px; } .select { width: 100%; border: none; box-shadow: none; background-color: #eaeaea; color: #000; height: 25px; padding-left: 5px; border-radius: 0px; font-size: 12px; } .shape.ajs-icon { font-size: 20px; } } } .messages-container { padding: 0px; margin-bottom: 0px; border: none; border-radius: 4px; background-color: #E1F5FE; margin-top: 0px; text-align: center; &.type-info { background-color: #E1F5FE; } &.type-error { background-color: #EF9A9A; } p.info { padding: 0px; margin: 0px; } p.error { padding: 0px; margin: 0px; } } } .footer { height: 25px; border: none; line-height: 25px; background-color: #616161; color: #CCC; text-align: center; .save-metadata { min-width: 10px; padding: 0; font-size: 25px; font-weight: normal; color: #fff; text-align: center; white-space: nowrap; background-color: #03A9F4; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 35px; width: 35px; margin: auto; position: relative; vertical-align: middle; margin-top: -25px; box-shadow: none; line-height: 40px; &:before { margin-left: -1px; } } } } /** * Plugin items editor */ &.plugin-items-editor { color: #616161; .heading { height: 30px; border: none; line-height: 25px; background-color: #616161; color: #CCC; .title { text-align: left; padding-left: 10px; margin: 0; color: #FFF; line-height: 30px; font-size: 14px; } } .body { .messages-container { padding: 5px 0px 5px 0px; margin-bottom: 11px; border: none; border-radius: 4px; background-color: #E1F5FE; margin-top: 10px; text-align: center; min-height: 25px; &.type-info { background-color: #E1F5FE; } &.type-error { background-color: #EF9A9A; } p.info { padding: 0px; margin: 0px; } p.error { padding: 0px; margin: 0px; } } ul.listOfSelectedItems { box-sizing: border-box; color: #cacaca; display: block; font-size: 14px; line-height: 20px; list-style-type: disc; margin-bottom: 0px; margin-top: 0px; padding-left: 0px; height: 285px; overflow-y: overlay; li.item { position: relative; display: block; padding: 0px; margin-bottom: 0; background-color: transparent; border: none; color: #000; box-shadow: none; font-size: 12px; &.error { border: 1px solid red; text-align: left; } .form-data { padding: 25px 0px 10px 0px; border: none; background-color: #eceff1; margin-right: 0; min-height: 56px; box-shadow: none; margin: 1px 0px 0px 0px; .form-input { margin: 0px 5px; box-shadow: none; min-height: 25px; .input { width: 100%; border: none; box-shadow: none; background-color: #eaeaea; color: #000; height: 25px; padding-left: 5px; border-radius: 5px; font-size: 12px; } } .form-controls { position: absolute; width: auto; height: 25px; top: 5px; right: 10px; padding: 0px; span.button { padding: 0px; font-size: 12px; font-weight: normal; text-align: center; white-space: nowrap; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 20px; width: 20px; margin: 0px 0px 0px 5px; position: relative; vertical-align: middle; padding-top: 0px; margin-top: 0; top: 0px; right: 0px; color: white; box-shadow: none; line-height: 23px; opacity: 1; filter: none; float: none; &:before { margin-left: -1px; } &.valid { background-color: #CACACA; visibility: hidden; &.valid.on { visibility: visible; background-color: #03A9F4; } } &.remove { background-color: #FFC107; } &.close { background-color: #757575; } } } } } } } .footer { height: 25px; border: none; line-height: 25px; background-color: #616161; color: #CCC; text-align: center; .button { min-width: 10px; font-size: 25px; font-weight: normal; color: #fff; text-align: center; white-space: nowrap; border: none; border-radius: 50%; cursor: pointer; display: inline-block; height: 35px; width: 35px; margin: 5px; position: relative; vertical-align: middle; margin-top: -25px; box-shadow: none; line-height: 40px; &.add { background-color: #00CC99; &:before { margin-left: -1px; } } &.validateAll { background-color: #03A9F4; &:before { margin-left: -1px; } } &.clear { background-color: #757575; &:before { margin-left: -1px; } } } } } } ================================================ FILE: src/assets/sass/_plugin-menu-contextuel.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** Plugin menu contextuel**/ .ajs .plugin-context-menu.dropdown-menu { width: 300px; padding: 0px 0px 0px 10px; margin: 0; text-align: left; list-style: none; background-color: #fff; -webkit-background-clip: padding-box; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, .15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); box-shadow: 0 6px 12px rgba(0, 0, 0, .175); z-index: 1000; &:before { bottom: -14px; border-top: 7px solid #555; } &:before, &:after, li:first-child:after { content: ''; display: block; position: absolute; left: 15px; width: 0; height: 0; border: 7px outset transparent; } li { color: #838ca2; text-shadow: none; margin: 0; padding: 0px 0px 0px 25px; border: 0; font-size: 100%; font: inherit; vertical-align: middle; height: 30px; list-style: none; line-height: 30px; display: block; position: relative; .ajs-icon { position: absolute; left: 0px; top: 3px; font-size: 24px; line-height: 28px; } &.disabled { a { cursor: default; } } } } ================================================ FILE: src/assets/sass/_plugin-overlay.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin overlay */ .ajs-plugin { &.plugin-overlay { display: block; color: #FFF; position: absolute; width: 100%; height: 100%; z-index: 98; top: 0; &.eraser { cursor: pointer; } .overlay-canvas { /*border: 1px solid red;*/ } .error { position: absolute; top: 9px; left: 0; width: 100%; line-height: 20px; color: white; font-size: 20px; background-color: red; font-weight: bold; } &.draw { cursor: crosshair; } .toolbox { width: 100px; position: absolute; top: 0; right: 0; border: none; padding: 0; margin: 0; cursor: move; opacity: 0.9; .add { .add-ctrl, .close-box, .add-shape-msg, .add-shape-rectangle, .add-shape-ellipse { height: 65px; width: 101px; background-color: #616161; color: white; font-size: 12px; line-height: 20px; text-align: center; box-shadow: 1px 1px 0px rgb(121, 121, 121); &.on { background-color: #99CC00; } } .add-shape-rectangle, .add-shape-ellipse { font-size: 50px; line-height: 75px; } .add-ctrl { background-color: #616161; .ctrl { background-color: #3cf; } } .close-box { background-color: #616161; .ctrl { background-color: transparent; border: 3px solid white; } } } .erase-box { height: 65px; width: 101px; background-color: rgba(49, 49, 49, 0.7); color: white; font-size: 12px; line-height: 20px; text-align: center; box-shadow: 1px 1px 0px rgb(121, 121, 121); &.on { background-color: #99CC00; } .ctrl { background-color: #E57373; } } .nav-box { background-color: rgba(121, 121, 121, 0.7); .nav-left-box, .nav-right-box { display: inline-block; text-align: center; width: 50px; height: 50px; margin: 0; padding: 0; line-height: 50px; .ctrl { margin: 0; padding: 0; &:hover { background-color: rgba(153, 204, 0, 0.7); } } } } .ctrl { height: 35px; width: 35px; display: inline-block; padding: 0px; font-size: 28px; color: #fff; text-align: center; white-space: nowrap; border: none; border-radius: 50%; cursor: pointer; margin: auto; position: relative; vertical-align: middle; box-shadow: none; line-height: 46px; margin: 10px 0px 0px 0px; border: 3px solid transparent; &.on { border: 3px solid rgb(153, 204, 0); } } .add-shapebox { background-color: rgba(49, 49, 49, 0.7); } } } } ================================================ FILE: src/assets/sass/_plugin-selected-item-editor.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.plugin-selected-item-editor { position: relative; .auto-fill-up-form { display: none; height: 60px; width: 700px; color: #000; background-color: #797979; position: absolute; bottom: 5px; z-index: 900; .message, .form-item { float: left; } .message { width: 520px; color: white; font-size: 16px; padding: 21px 0px 0px 18px; } .form-item { } &.on { display: block; } &:after { clear: both; } .form-item { .form-ctrl-item-yes { height: 60px; width: 90px; background-color: #1485cc; border: none; color: white; font-size: 16px; font-weight: bold; } .form-ctrl-item-no { height: 60px; width: 90px; background-color: #0b486c; border: none; color: white; font-size: 16px; font-weight: bold; } } } .form { height: 50px; width: 100%; color: #000; .form-item { float: left; .form-item-label { height: 60px; background-color: #f2f2f2; width: 170px; border: none; color: #666666; font-size: 16px; text-align: center; font-weight: normal; } .form-item-tcin, .form-item-tcout { height: 60px; width: 100px; border: none; color: #666666; font-size: 16px; text-align: center; &.error { background-color: #ba6868; } } .form-ctrl-item-tcin, .form-ctrl-item-tcout { background-color: #1485cc; border-radius: 0; color: #FFFFFF; display: block; font-size: 16px; height: 60px; line-height: 20px; padding: 10px; text-transform: uppercase; outline: none; width: 70px; border: none; padding: 0px; } .form-ctrl-item-valid { background-color: #797979; height: 60px; border: none; color: white; font-size: 16px; &.valid { background-color: #1485cc; } &:hover { background-color: #6ab6e8; } } .form-ctrl-item-delete { background-color: #B71C1C; height: 60px; border: none; color: white; font-size: 16px; display: none; &.on { display: block; } &:hover { background-color: #C62828; } } .form-ctrl-item-close-item { background-color: #B71C1C; height: 60px; border: none; color: white; font-size: 16px; display: none; &.on { display: block; } &:hover { background-color: #C62828; } } .form-ctrl-item-auto-fill-up { background-color: #a1a1a1; width: 60px; height: 60px; border: none; font-size: 52px; font-weight: 100; padding-top: 10px; color: white; &:hover { background-color: #6ab6e8; } } &.delete { display: none; &.on { display: block; } .form-ctrl-item-delete { background-color: #22baa0; } } &.label { background-color: #f2f2f2; padding: 0px; border: medium none; border-radius: 0; box-shadow: none; display: inline-block; margin: 0; border: none; } } } &.ajs-plugin { overflow: visible !important; } } ================================================ FILE: src/assets/sass/_plugin-storyboard.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.plugin-storyboard { display: none; color: #FFF; position: absolute; width: 100%; height: 100%; z-index: 98; top: 0; .thumbnail { height: 90px; width: 160px; background-color: #313131; background-position: 0px -90px; background-repeat: no-repeat; position: absolute; bottom: 45px; margin-top: 0px; margin-right: 0px; margin-bottom: 3px; left: 50%; border-radius: 2px; border: solid #000 2px; z-index: 90; } .filmstrip { position: absolute; width: 100%; text-align: center; margin: 0; padding: 0; opacity: 0.7; z-index: 90; -webkit-filter: grayscale(0.3); -moz-filter: grayscale(0.3); -ms-filter: grayscale(0.3); -o-filter: grayscale(0.3); .storyboard-thumbnail { background-color: #313131; background-position: 0px -90px; background-repeat: no-repeat; position: absolute; margin-top: 0px; margin-right: 0px; margin-bottom: 3px; border-radius: 2px; border: solid #000 2px; } } .preview-storyboard { text-align: center; display: block; position: absolute; margin: 0px; padding: 0px; .thumbnail-overlay { height: 100%; width: 100%; position: relative; border: solid #000 2px; visibility: visible; z-index: 80; filter: blur(5px); -webkit-filter: blur(3px) grayscale(0.8); -moz-filter: blur(3px) grayscale(0.8); -ms-filter: blur(3px) grayscale(0.8); -o-filter: blur(3px) grayscale(0.8); } } } ================================================ FILE: src/assets/sass/_plugin-text-sync.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin text sync */ .ajs-plugin.plugin-text-sync { background: #e6e6e6; margin: 0; padding: 0; color: black; .header { overflow: hidden; zoom: 1; display: block; margin: 0; padding: 0; .resume { background: #555; color: white; padding: 15px; text-align: left; font-size: 14px; overflow: hidden; zoom: 1; .heading { font-size: 24px; font-weight: 100; color: white; line-height: 1.1; padding: 0; margin: 0; } } } .line-component { padding: 10px; overflow-y: auto; height: 100%; margin: 0; .line { box-sizing: border-box; color: rgb(0, 0, 0); display: list-item; font-size: 14px; list-style-image: none; list-style-position: outside; list-style-type: none; margin: 0; overflow-x: hidden; overflow-y: hidden; text-align: left; padding: 10px; .info { box-sizing: border-box; color: rgb(0, 0, 0); display: block; float: left; font-family: Arial, Helvetica, sans-serif; font-size: 14px; margin-right: 10px; text-align: left; .thumb { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0IwMTkyREMwMTAwMTFFNDk0QTM5OTI4MzY1OEFGQUEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0IwMTkyREQwMTAwMTFFNDk0QTM5OTI4MzY1OEFGQUEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQjAxOTJEQTAxMDAxMUU0OTRBMzk5MjgzNjU4QUZBQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQjAxOTJEQjAxMDAxMUU0OTRBMzk5MjgzNjU4QUZBQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph56Pv8AAAJASURBVHja7JnLiupAEIY1BlG8492gK1HceseFD+0juNAHcCG6GlBBBVHEG15wfk5ARDj2JHYn00zVqglN1/91qquqE2en03HIbIpDciMAAiAAAiAAApDa1J9M0jStWCz6fD4rle33+9FoNJvNPgWA+nK5bP3WYr90v+8Z2CFUKBRsjBCmdzaA3++3EYDpXTW64vF4XK1W9/tdhFyn0xmNRr1eL+dD/Hywut3u9XoVmFVUtd1u/zxhGEuj8/lcqHoY1ocXUXXgdrtZEPeGvKgOWy2fz2cyGZyrwWBwOp1EFTJBlk6nS6USBqFQCKHf7/clayXC4fBjDAb5eqH1ev0YbzYbgb2QIEO2QejjDBwOh+FwKB8A7OufUTvNyVwuVzabVRRlMplcLhfJAKC+0Wigk8E4l8v1er3z+SzNjQzq6/W6rh4WCARarZbb7ZYDQFcfi8WeH74weDyeSqWCV2Q634sCQMTXarUX9S8MUI8B0mUikcAgEon8FgCor1ar8Xj8fxN0BtijPUbL0Gw2OTIoH6pPJpPvp4Hhpbnny2AeADHNVP/m1sKLwTxAKpX68ObFhcHOSsyFwTwAl7ulzvDcV1sHMJ1Oeb0H1IdgMGh1K4FOeLlc8vreiGS13W6t7oUWi4Xt3aixEDL0ycm0GfJiDEDTNNzEUcJEbaeiYH14ERVCevX9VRca+kNDAARAAAQgGGC329moj+mdDTAej20EYHpnV2L9N63EP7p1BuZCdIgJgAAIgAAIgAD+IsC3AAMAzUKl+/tbh2cAAAAASUVORK5CYII='); cursor: pointer; width: 64px; background-size: cover; height: 64px; } .badge { border-radius: 10px; border: none; cursor: pointer; display: inline-block; min-width: 10px; padding: 3px 7px; font-size: 12px; font-weight: 700; color: #fff; line-height: 1; vertical-align: baseline; white-space: nowrap; text-align: center; background-color: #999; &.tcin { margin: 4px 0; } &.tcout { margin: 0 0 4px 0; } &.tcin, &.tcout { clear: both; float: left; border-radius: 3px; } } } &.on { background-color: #d8d8d8; .content { .ajs-progress .ajs-progress-bar { background-color: $mainColor; } } } &.on .info .badge.tcin, &.on .info .badge.tcout { background-color: $mainColor; cursor: pointer; } .content { overflow: hidden; zoom: 1; text-align: left; font-size: 14px; .heading { text-align: left; font-size: 14px; } .text { text-align: left; font-size: 14px; .word { cursor: pointer; &.on { font-weight: bold; } } } .ajs-progress { border-radius: 3px; width: 100%; height: 2px; .ajs-progress-bar { background-color: #d8d8d8; height: 1px; } } } } } } ================================================ FILE: src/assets/sass/_plugin-timeline.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin time line */ $modulesSizeListNames: lg, md, sm, xs; $modulesSizeList: 110px, 80px, 60px, 25px; .ajs-plugin.plugin-timeline { position: relative; background-color: #000; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; .timeline-cursor { border-left: 1px solid $mainColor; display: block; height: 100%; width: 1px; left: 0%; position: absolute; z-index: 100; bottom: 30px; } .timeline-progress-container { position: absolute; width: 100%; height: 102px; background-color: $mainBackgroundColor; z-index: 90; right: 100%; } .timeaxis { /* tools bar */ .toolsbar { background-color: #3f3f3f; padding: 5px 10px 0 10px; height: 40px; .ajs-row { .ajs-col { float: left; position: relative; min-height: 1px; padding: 0px; margin: 0px; &:after { clear: both; } } .leftContainer { width: 16.66666667%; text-align: left; } .middleContainer { width: 66.66666667%; text-align: center; } .rightContainer { width: 16.66666667%; text-align: right; } } button.ajs-icon { display: inline-block; color: white; background-color: #333; border-radius: 50%; border: none; box-shadow: none; padding: 0; width: 30px; height: 30px; padding: 0 2px 0 1px; line-height: 36px; font-size: 20px; &:hover { background-color: $mainColor; } } } /**Module TimeAxe**/ .module-timeaxis { position: relative; background-color: #333; height: 100px; margin-top: 2px; .line { height: 20px; position: absolute; top: 30px; width: 100%; margin-top: 5px; z-index: 99; border-bottom: 1px solid white; } .line-content { text-align: center; position: absolute; top: 50%; width: 100%; height: auto; z-index: 99; } .time-grid { height: 10px; width: 1px; padding-top: 2px; display: block; position: absolute; border-right: 1px solid #FFF; } .time-grid span.time { display: block; width: 55px; font-size: 12px; position: relative; top: -20px; line-height: 15px; left: 50%; margin-left: -27px; cursor: pointer; } } .timeaxis-label { display: none; } .toolbar-container { position: absolute; top: 0; right: 20px; .plugin-btn { border: none; box-shadow: none; background: none; color: #6c6c6c; font-size: 17px; line-height: 25px; } } &.off { height: 25px; background-color: #333; .toolsbar { display: none; } .module-timeaxis { display: none; } .timeaxis-label { position: absolute; top: 0; display: block; .label { font-size: 11px; padding: 0px 0px 0px 5px; margin: 0; } } } } /**Composants du timeline**/ .components { display: block; position: relative; width: 100%; overflow: hidden; .cuepoints-component, .segments-component, .images-component, .histogram-component, .visual-component { position: relative; cursor: pointer; } .cuepoints-component .module-cuepoints, .segments-component .module-segments, .images-component .module-images, .histogram-component .module-histogram, .visual-component .module-visual { position: relative; background-color: #333; height: 100px; margin-top: 2px; text-align: left; } .cuepoints-component.activated .module-cuepoints, .segments-component.activated .module-segments, .images-component.activated .module-images, .histogram-component.activated .module-histogram, .visual-component.activated .module-visual { background-color: #3f3f3f; } .cuepoints-component .module-cuepoints .line-content, .segments-component .module-segments .line-content, .images-component .module-images .line-content, .visual-component .module-visual .line-content { position: absolute; top: 50%; width: 100%; height: auto; z-index: 99; } @mixin generate-theme($n, $i: 1) { @for $i from 1 through 4 { $sizeName: nth($modulesSizeListNames, $i); .component.cuepoints-component.#{$sizeName} .module-cuepoints, .component.segments-component.#{$sizeName} .module-segments, .component.images-component.#{$sizeName} .module-images, .component.histogram-component.#{$sizeName} .module-histogram, .component.visual-component.#{$sizeName} .module-visual { height: nth($modulesSizeList, $i); } .#{sizeName} .focus-container { .ui-resizable-handle { height: nth($modulesSizeList, $i); } } } } @include generate-theme(4); $sizeName: nth($modulesSizeListNames, 4); .cuepoints-component.#{$sizeName} .module-cuepoints .line-content, .segments-component.#{$sizeName} .module-segments .line-content, .images-component.#{$sizeName} .module-images .line-content, .histogram-component.#{$sizeName} .module-histogram .line-content, .visual-component.#{$sizeName} .module-visual .line-content { display: none; } .component.#{$sizeName} .sub, .component.#{$sizeName} .bottom-toolbar-container, .component.#{$sizeName} .focus-container { display: none; } .cuepoints-component .module-cuepoints .line, .segments-component .module-segments .line, .images-component .module-images .line, .histogram-component .module-images .line, .visual-component .module-visual .line { background-color: #fff; height: 1px; position: absolute; z-index: 98; top: 2px; width: 100%; } .cuepoints-component .module-cuepoints .cuepoint { position: absolute; vertical-align: middle; cursor: pointer; font-size: 20px; line-height: 13px; z-index: 98; margin-left: -10px; &.selected { animation-name: ajs-bounce; -webkit-animation-name: ajs-bounce; animation-duration: 1.6s; -webkit-animation-duration: 1.6s; animation-timing-function: ease; -webkit-animation-timing-function: ease; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; } } .segments-component .module-segments .segment { position: absolute; height: 7px; width: 1px; float: left; z-index: 99; background-color: $mainColor; cursor: pointer; border: none; margin: 0; padding: 0; .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } .ui-resizable-handle { position: absolute; font-size: .1px; z-index: 99999; display: block; } &.selected { /**hatch**/ animation-name: ajs-pulse; -webkit-animation-name: ajs-pulse; animation-duration: 2s; -webkit-animation-duration: 2s; animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; visibility: visible !important; } &.marker { height: 2px; margin: 0px; padding: 0px; top: 2px; .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: -3px; height: 8px; background-color: inherit; } .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: -3px; height: 8px; background-color: inherit; } } } .visual-component .module-visual { .cuepoint { position: absolute; vertical-align: middle; cursor: pointer; font-size: 20px; line-height: 13px; z-index: 98; margin-left: -10px; top: -2px; &.selected { animation-name: ajs-bounce; -webkit-animation-name: ajs-bounce; animation-duration: 1.6s; -webkit-animation-duration: 1.6s; animation-timing-function: ease; -webkit-animation-timing-function: ease; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; } } .segment { position: absolute; height: 7px; width: 1px; float: left; z-index: 99; background-color: $mainColor; cursor: pointer; .cuepoint { top: -7px; margin-right: -10px; } &.selected { /**hatch**/ animation-name: ajs-hatch; -webkit-animation-name: ajs-hatch; animation-duration: 2s; -webkit-animation-duration: 2s; animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out; transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; -webkit-transform-origin: 50% 100%; animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite; visibility: visible !important; } &.marker { height: 2px; margin: 0px; padding: 0px; top: 2px; .ui-resizable-w { cursor: w-resize; width: 15px; left: 0px; top: -6px; height: 15px; background-color: inherit; position: absolute; } .ui-resizable-e { cursor: e-resize; width: 15px; right: 0px; top: -6px; height: 15px; background-color: inherit; position: absolute; } } } } .images-component .module-images .image { position: absolute; float: left; z-index: 99; background-color: none; height: 50px; top: -25px; background-repeat: no-repeat; line-height: 50px; cursor: pointer; &.on { z-index: 100; .content { } &.segment { z-index: 100; border: solid 1px $mainColor; margin-top: -1px; .content { /*height: 45px;*/ } } } .content { height: 30px; z-index: 1; position: absolute; top: 15px; } hr.flow { border-color: #FFF; color: #FFF; display: block; margin: 0; padding: 0; position: relative; height: 0px; top: 28px; z-index: 0; border-style: double; border-width: 1px; width: 100%; &:after, &:before { display: inline-block; font-family: FontAwesome; font-size: 1.1em; position: absolute; top: -25px; } &:after { right: -6px; content: "\f111"; } &:before { left: -3px; content: "\f142"; } } } .histogram-component .module-histogram .cuepoint { position: absolute; vertical-align: middle; cursor: pointer; font-size: 16px; line-height: 8px; z-index: 98; margin-left: -5px; } .histogram-component .module-histogram .label { display: block; position: absolute; top: 0px; } .histogram-component .module-histogram .line-content { position: relative; height: 100%; } .cuepoints-component .module-cuepoints .label, .segments-component .module-segments .label, .images-component .module-images .label, .histogram-component .module-histogram .label, .visual-component .module-visual .label { background-color: transparent; -webkit-touch-callout: text; -webkit-user-select: text; -khtml-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; padding: 0px 0px 0px 5px; margin: 0; display: inline-block; } .cuepoints-component .module-cuepoints .callback, .segments-component .module-segments .callback, .images-component .module-images .callback, .histogram-component .module-histogram .callback, .visual-component .module-visual .callback { background-color: transparent; -webkit-touch-callout: text; -webkit-user-select: text; -khtml-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; padding: 0px 0px 0px 5px; margin: 0; display: inline-block; } .sub.cuepoints-component .module-cuepoints, .sub.segments-component .module-segments, .sub.images-component .module-images, .sub.images-histogram .module-histogram, .sub.visual-histogram .module-visual { background-color: rgba(100, 100, 100, 0.68); } .focus-container { left: 0%; width: 222px; display: block; background-color: rgba(100, 100, 100, 0.68); height: 50%; border: 0px solid #333; box-shadow: none; position: absolute; top: 0px; display: block; z-index: 100; min-width: 41px; &.zoom { background-color: $mainBackgroundColor; height: 100%; } .ui-resizable-handle { background-color: #6c6c6c; width: 20px; height: 100%; text-align: center; vertical-align: middle; display: inline-block; margin-left: 0px; margin-right: 0px; &.ui-resizable-w { float: left; font-size: 20px; position: relative; &:before { -webkit-transform: translateX(-50%) translateY(-50%) rotate(-90deg); -ms-transform: translateX(-50%) translateY(-50%) rotate(-90deg); transform: translateX(-50%) translateY(-50%) rotate(-90deg); display: block; width: 20px; height: 20px; margin: 2px 0px 0px 12px; padding: 0px; position: absolute; top: 50%; } } &.ui-resizable-e { float: right; font-size: 20px; &:before { -webkit-transform: translateX(-50%) translateY(-50%) rotate(-90deg); -ms-transform: translateX(-50%) translateY(-50%) rotate(-90deg); transform: translateX(-50%) translateY(-50%) rotate(-90deg); display: block; width: 20px; height: 20px; margin: 2px 0px 0px 12px; padding: 0px; position: absolute; top: 50%; } } } } .bottom-toolbar-container { position: absolute; bottom: 5px; left: 5px; display: block; .focus-btn { background-color: transparent; border: none; color: white; font-size: 20px; line-height: 20px; } } .component.focus-off { .focus-container { display: none; } .bottom-toolbar-container { display: block; } .sub { display: none; } } .component.focus-on { .focus-container { display: block; } .bottom-toolbar-container { display: none; } .sub { display: block; } } $smallSizeName: extract($modulesSizeListNames, 4); .component.#{$smallSizeName} .sub, .component.#{$smallSizeName} .bottom-toolbar-container, .component.#{$smallSizeName} .focus-container { display: none; } .timecursor { left: 0%; position: absolute; top: 0px; width: 1px; border-left: 1px solid $mainColor; height: 100%; } .toolbar-container { position: absolute; top: 0; right: 20px; .plugin-btn { border: none; box-shadow: none; background: none; color: #6c6c6c; font-size: 17px; line-height: 25px; } .close-btn, .sort-btn, .expand-btn { color: $BtToolContColor; height: 28px; line-height: 28px; text-align: center; width: 28px; cursor: pointer; border: none; background: transparent; font-size: 20px; } .nav-controls { color: $BtToolContColor; display: inline-block; float: left; line-height: 28px; margin-right: 15px; text-align: center; vertical-align: middle; font-size: 20px; padding: 0; .prev-control { cursor: pointer; border: none; background: transparent; color: $BtToolContColor; font-size: 20px; padding: 0; } .next-control { cursor: pointer; border: none; background: transparent; color: $BtToolContColor; font-size: 20px; padding: 0; } } } } /**Bar de controle**/ .module-nav-bar-container { .info { padding-left: 15px; line-height: 30px; } .toolsbar { height: 30px; padding: 0px; background-color: #3f3f3f; button.ajs-icon { border-radius: 0%; width: 30px; line-height: 25px; border: none; background-color: transparent; color: white; } } .leftContainer { text-align: left; border: none; background-color: transparent; float: left; width: 16.66666667%; } .middleContainer { text-align: center; border: none; background-color: transparent; float: left; width: 66.66666667%; } .rightContainer { text-align: right; border: none; background-color: transparent; float: right; width: 16.66666667%; .config-menu { padding-right: 30px; .config-btn { width: 30px; line-height: 29px; cursor: pointer; font-size: 2.4em; } } .config-menu-list { background: #FFF; border: none; box-shadow: none; margin: 0px; position: absolute; bottom: 30px; border-radius: 0px; right: 1px; width: 200px; list-style: none; padding: 5px 0px 5px 5px; li { padding-left: 5px; color: #000; cursor: pointer; text-align: left; } } } &:after { clear: both; } } /**resizeable component**/ .ui-resizable-s { display: block; height: 30px; width: 30px; font-size: 30px; position: absolute; left: 100%; bottom: 0; margin-left: -45px; padding-left: 15px; display: inline-block; vertical-align: middle; line-height: 40px; font-weight: normal; font-style: normal; cursor: s-resize; } } ================================================ FILE: src/assets/sass/_plugin-watermark.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin.plugin-watermark { display: block; color: #FFF; position: absolute; width: 100%; height: 100%; z-index: 98; top: 0; .watermark { background-color: transparent; background-repeat: no-repeat; position: absolute; } } ================================================ FILE: src/assets/sass/_plugin.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Plugin */ .ajs-plugin { font-family: $fontMain; color: #FFF; clear: both; overflow: hidden; font-size: 11px; .error { text-align: center; } .loader { text-align: center; width: 100%; top: 50%; font-size: 3em; } /* Custom de la scrollbar */ &::-webkit-scrollbar, & ::-webkit-scrollbar { width: 10px; } &::-webkit-scrollbar-thumb, & ::-webkit-scrollbar-thumb { background: rgba(108, 108, 108, .6); } } @import"_player-custom-control-bar"; @import"_plugin-timeline"; @import"_plugin-text-sync"; @import"_plugin-captions"; @import"_plugin-overlay"; @import"_plugin-watermark"; @import"_plugin-menu-contextuel"; @import"_plugin-editor"; @import"_plugin-selected-item-editor"; @import"_plugin-storyboard"; @import"_plugin_d3js_chart"; ================================================ FILE: src/assets/sass/_plugin_d3js_chart.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ .ajs-plugin .plugin-db3-js-chart { border-top: solid 2px $mainBackgroundColor; margin-top: -13px; .components { .component { position: relative; .timeline-cursor { left: 0px; width: 1px; height: 100%; display: block; background-color: $mainColor; position: absolute; z-index: 100; bottom: 25px; margin-left: -3px; } // Background box .module-chart { background-color: $backgroundColor; display: block; width: 100%; height: 200px; } // grid-line cursor .line { background-color: $inverseBackgroundColor; display: block; width: 100%; height: 3px; top: 12px; position: relative; } // Background Cursor .focus-container { display: block; width: 100%; height: 25px; background-color: lighten($secondaryBackgroundColor, 10%); margin-top: -3px; // Cursor middle segment .focus-component { background-color: $mainColor; cursor: e-resize; display: block; height: 3px; position: relative; top: 12px; // Left and Right handle cursor .ui-resizable-handle.ui-resizable-w.ajs-icon, .ui-resizable-handle.ui-resizable-e.ajs-icon { border-radius: 30%; cursor: pointer; height: 15px; width: 15px; display: block; background-color: white; top: -7px; // Add grid indicator &:before { content: ""; display: block; border-left: dashed 1px $mainColor; height: 173px; position: absolute; top: -175px; left: 7px; } } } } // Override SVG color svg.nvd3-svg { .tick { opacity: .6; text { fill: white; } } .nv-legend-text { fill: white; font-size: 14px; } } } } } ================================================ FILE: src/assets/sass/main.scss ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /************************************************** ****************** *****VARIABLES ***************** **************************************************/ /***** FONTS ****/ $fontMain: Arial, Helvetica, sans-serif; /***** COLORS ****/ $BtToolContColor : #6c6c6c; /************************************************** ****************** THEMES PROJETS ***************** **************************************************/ /***** PLAYER PROJET GEN ****/ $mainColor: #0CF; $primaryColor: #0d8bc7; $secondaryColor: #4cd1d5; $mainBackgroundColor: rgba(19, 231, 240, 0.68); $mainGradient: linear-gradient(to right, #13e7f0, #0c7abf); $inverseBackgroundColor: rgba(51, 51, 51, 0.68); $backgroundColor : #2e2e2e; $primaryBackgroundColor : #292929; $secondaryBackgroundColor : #393939; // Devices width $screen-xx-min: 320px; $screen-xs-min: 480px; $screen-sm-min: 768px; $screen-md-min: 992px; $screen-lg-min: 1200px; @import "_ajs-animations"; @import "_ajs-mixins"; @import "_ajs-webfont"; @import "_default-style"; @import "_player"; @import "_plugin"; // test ================================================ FILE: src/helpers/browser-feature-detection.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * This class provides borwser utility functions. * @class BrowserFeatureDetection * @namespace fr.ina.amalia.player.helpers * @module player-utils * @constructor * @param {Object} settings Defines the configuration of this class */ $.Class("fr.ina.amalia.player.helpers.BrowserFeatureDetection", { /** * True if mobile device * @method isMobilePlatform * @return {Array} */ isMobilePlatform: function () { return (navigator.userAgent.match(/(iPod|iPhone|iPad)/) || navigator.userAgent.toLowerCase().indexOf('android') > -1); } }, { /** * Defines configuration * @property settings * @type {Object} * @default {} */ settings: {}, /** * In charge to render messages in the web console output * @property logger * @type {Object} * @default null */ logger: null, /** * Init this class * @constructor * @method init * @param {Object} settings */ init: function (settings) { this.settings = $.extend({ debug: false }, settings || {}); if (fr.ina.amalia.player.log !== undefined && fr.ina.amalia.player.log.LogHandler !== undefined) { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } }, /** * Method checks if the browser can play the specified audio/video * @method isSupportsVideos * @returns {Boolean} Return false if browser don't support this audio/video * file. */ isSupportsVideos: function () { if (!!document.createElement('video').canPlayType) { if (this.logger !== null) { this.logger.info("Support html5"); } return true; } else { if (this.logger !== null) { this.logger.info("Can't support html5"); } return false; } }, /** * Method checks if the browser can play the specified mp4 file. * @method isSupportsMp4 * @returns {Boolean} Return false if browser don't this audio/video file. */ isSupportsMp4: function () { if (!this.isSupportsVideos()) { return false; } else { var video = document.createElement("video"); if (video.canPlayType('video/mp4')) { if (this.logger !== null) { this.logger.info("Support mp4"); } return true; } else { if (this.logger !== null) { this.logger.info("Can't support mp4"); } return false; } } } }); ================================================ FILE: src/helpers/html5-helper.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * This class provides html5 utility functions * @class HTML5Helper * @namespace fr.ina.amalia.player.helpers * @module player-utils */ $.Class("fr.ina.amalia.player.helpers.HTML5Helper", { /** * Method checks whether the document is in full-screen mode. * @method inFullScreen * @returns {Boolean} Return true if the document is in full-screen mode. */ inFullScreen: function () { if ( document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled ) { if ( document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement ) { return true; } } return false; }, /** * Method in charge to toggle full-screen mode * @method toggleFullScreen * @param dom container * @param force force to call full-screen mode * @return {Boolean} Return true if in full-screen mode. */ toggleFullScreen: function (dom, force) { var inFullScreen = fr.ina.amalia.player.helpers.HTML5Helper.inFullScreen(); if (inFullScreen === false || force === true) { var requestFullScreen = dom.requestFullScreen || dom.webkitRequestFullScreen || dom.mozRequestFullScreen || dom.msRequestFullscreen || dom.webkitEnterFullscreen; if (typeof requestFullScreen !== "undefined" && requestFullScreen) { requestFullScreen.call(dom); return true; } } else { var cancelFullScreen = document.cancelFullScreen || document.mozCancelFullScreen || document.webkitCancelFullScreen || document.exitFullscreen || document.msExitFullscreen; if (typeof cancelFullScreen !== "undefined" && cancelFullScreen) { cancelFullScreen.call(document); return false; } } } }, {}); ================================================ FILE: src/helpers/utilities-helper.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * This class provides some utility functions. * @class UtilitiesHelper * @namespace fr.ina.amalia.player.helpers * @module player-utils */ $.Class("fr.ina.amalia.player.helpers.UtilitiesHelper", { /** * Method in charge to format time * @method formatTime * @param seconds * @param defaultFps frames per second * @param format Format specifier h/m/s/f/ms/mms * @return {String} return format time */ formatTime: function (seconds, defaultFps, format) { var formatTime = formatTime || "f"; var FPS = defaultFps || 25; var _fps = Math.floor((Math.floor((seconds - Math.floor(seconds)) * 100000) * FPS) / 100000); var minutes = Math.floor(seconds / 60); var hours = Math.floor(minutes / 60); var milliseconds = seconds % 60; seconds = Math.floor(seconds % 60); minutes = Math.floor(minutes % 60); minutes = (minutes >= 10) ? minutes : "0" + minutes; hours = (hours >= 10) ? hours : "0" + hours; seconds = (seconds >= 10) ? seconds : "0" + seconds; _fps = (_fps >= 10) ? _fps : "0" + _fps; switch (format) { case 'h' : formatTime = hours; break; case 'm' : formatTime = hours + ":" + minutes; break; case 's' : formatTime = hours + ":" + minutes + ":" + seconds; break; case 'seconds' : formatTime = parseFloat(parseFloat(hours) * 3600 + parseFloat(minutes) * 60 + parseFloat(milliseconds)).toFixed(4); break; case 'mms' : formatTime = hours + ":" + minutes + ":" + seconds + "." + milliseconds.toFixed(4).split('.')[1]; break; case 'ms' : formatTime = hours + ":" + minutes + ":" + seconds + "." + milliseconds.toFixed(2).split('.')[1]; break; case 'f' : formatTime = hours + ":" + minutes + ":" + seconds + ":" + _fps; break; default : formatTime = hours + ":" + minutes + ":" + seconds + ":" + milliseconds.toFixed(2).split('.')[1]; } return formatTime; }, /** * Method to get time range by interval * @method getTimeRange * @param duration duration in second * @param interval * @param defaultFps frames per second */ getTimeRange: function (duration, interval, defaultFps) { var ranges = []; var FPS = defaultFps || 25; var _interval = (typeof interval === "undefined") ? "1" : interval; duration = Math.floor(duration); for (var start = 0; start <= duration; start += _interval) { if (interval === 'f') { start = Math.floor(start); for (var iFps = 0; iFps < FPS; iFps++) { start += (1000 / FPS) / 1000; ranges.push(fr.ina.amalia.player.helpers.UtilitiesHelper.formatTime(start, defaultFps)); } } else { ranges.push(fr.ina.amalia.player.helpers.UtilitiesHelper.formatTime(start, defaultFps)); } } return ranges; }, /** * Method in charge to return range * @param {Number} startTime * @param {Number} endTime * @param {Number} interval * @return {Array} */ getRangesWithStartAndEndTime: function (startTime, endTime, interval) { var ranges = []; var _interval = (typeof interval === "undefined") ? "1" : interval; for (var start = startTime; start <= endTime; start += _interval) { ranges.push(start); } return ranges; }, /** * Converts the specified hour to seconds. * @method convertHourToSeconde * @param _time format HH:MM:SS */ convertHourToSeconde: function (_time) { var time = null; // regex patter to search on var patt = /\d{2}:\d{2}:\d{2}/; // return the matching date string var result = patt.exec(_time); if (result !== null) { result = _time.split(':'); var hours = Math.floor(result[0]); var minutes = Math.floor(result[1]); var seconds = parseFloat(result[2]); time = (hours * 60 * 60) + (minutes * 60) + seconds; } return time; }, /** * Converts the specified hour to seconds. * @method convertTimeFPSToSeconde * @param _time format HH:MM:SS:FF * @param _fps fps */ convertTimeFPSToSeconde: function (_time, _fps) { var time = null; var FPS = _fps || 25; // regex patter to search on var patt = /\d{2}:\d{2}:\d{2}:\d{2}/; // return the matching date string var result = patt.exec(_time); if (result !== null) { result = _time.split(':'); var hours = Math.floor(result[0]); var minutes = Math.floor(result[1]); var seconds = parseFloat(result[2]); var f = parseFloat(result[3]); time = (hours * 60 * 60) + (minutes * 60) + seconds + ((f * 1000 / FPS) / 1000); } return time; }, /** * Convert Base64 string to array encoding * @method uint6ToB64 * @param {String} nUint6 * @return {Number} */ uint6ToB64: function (nUint6) { return nUint6 < 26 ? nUint6 + 65 : nUint6 < 52 ? nUint6 + 71 : nUint6 < 62 ? nUint6 - 4 : nUint6 === 62 ? 43 : nUint6 === 63 ? 47 : 65; }, /** * Array of bytes to base64 string decoding * @method b64ToUint6 * @param {String} nChr * @return {Number} */ b64ToUint6: function (nChr) { return nChr > 64 && nChr < 91 ? nChr - 65 : nChr > 96 && nChr < 123 ? nChr - 71 : nChr > 47 && nChr < 58 ? nChr + 4 : nChr === 43 ? 62 : nChr === 47 ? 63 : 0; }, /** * Decode base64 to array * @method base64DecToArr * @param {String} sBase64 * @param {Number} nBlocksSize * @return {Number} */ base64DecToArr: function (sBase64, nBlocksSize) { var sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length, nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen); for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) { nMod4 = nInIdx & 3; nUint24 |= fr.ina.amalia.player.helpers.UtilitiesHelper.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4; if (nMod4 === 3 || nInLen - nInIdx === 1) { for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255; } nUint24 = 0; } } return taBytes; }, /** * In charge to create unique id * @method generateUUID */ generateUUID: function (prefix) { var d = new Date().getTime(); var p = prefix || ''; var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c === 'x' ? r : (r && 0x3 | 0x8)).toString(16); }); return p + uuid; }, /** * Clear HTML escape * @param {type} str * @return {unresolved} */ htmlEscape: function (str) { return String(str) .replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } }, {}); ================================================ FILE: src/i18n/player-error-message-en.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ fr.ina.amalia.player.PlayerErrorMessage.ACCESS_DENIED = 'Access denied.'; fr.ina.amalia.player.PlayerErrorMessage.MEDIA_FILE_NOT_FOUND = 'Error Loading Media.'; fr.ina.amalia.player.PlayerErrorMessage.EXCEPTION = 'An exception occurred.'; fr.ina.amalia.player.PlayerErrorMessage.HTTP_ERROR = 'Http response at 400 or 500 level.'; fr.ina.amalia.player.PlayerErrorMessage.ABORT = 'Your request has been interrupted.'; fr.ina.amalia.player.PlayerErrorMessage.TIMEOUT = 'Timeout.'; fr.ina.amalia.player.PlayerErrorMessage.ERROR_LOAD_PLUGIN = 'Error during plugin initialization.'; fr.ina.amalia.player.PlayerErrorMessage.CUSTOM_ERROR = 'An error has occurred on your player.'; fr.ina.amalia.player.PlayerErrorMessage.ERROR = 'Error has occurred please try again later.'; fr.ina.amalia.player.PlayerErrorMessage.DEFAULT = 'Error has occurred please try again later.'; fr.ina.amalia.player.PlayerErrorMessage.ERROR_HTML5_SUPPORT = 'Error loading player: HTML5 video not supported'; fr.ina.amalia.player.PlayerErrorMessage.ERROR_MANIFEST_DASH = 'Error to load manifest dash'; ================================================ FILE: src/i18n/player-message-en.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ fr.ina.amalia.player.PlayerMessage.PLAYER_OPENSOURCE_LINK = 'Available as open source.'; fr.ina.amalia.player.PlayerMessage.PLUGIN_OVERLAY_CONTEXT_MENU_ENABLED_DISABLED_PLUGIN = 'Enable or disable plugin overlay.'; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_ELEMENTS = "items."; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_ZOOM_IN = "Zoom in"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_ZOOM_OUT = "Zoom out"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_CHANGE_DISPLAY = "Switch lines height"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_SLIDE_LEFT = "Slide Left"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_SLIDE_RIGHT = "Slide Right"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_SCROLL_UP = "Scroll Up"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_SCROLL_DOWN = "Scroll Down"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_SHOW_HIDE_TOOTIP = "Enable/disable the help tooltip"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_EXPAND = "Expand"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_SORT = "Sort"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_NAV_POINT_PREV = "Go to previous marker"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_NAV_POINT_NEXT = "Go to next marker"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_TIMEAXIS = "Time axis"; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_CLOSE = "Close"; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_LIST_EDITOR_LABEL_HEADER = "Metadata list editor"; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_LABEL_HEADER = "Metadata block editor"; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_ITEMS_EDITOR_LABEL_HEADER = "Metadata items editor"; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_ID = 'Id'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_LABAL = 'Label'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_TYPE = 'Type'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_DESCRIPTION = 'Description'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_REFERENCE = 'Reference'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_AUTHOR = 'Author'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_SHAPE = 'Shape'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_COLOR = 'Color'; fr.ina.amalia.player.PlayerMessage.PLUGIN_METADATA_ITEMS_EDITOR_NEED_METADTA = 'You need to select metadata item type.'; fr.ina.amalia.player.PlayerMessage.PLUGIN_TIMELINE_LABEL_BIND = "Bind/Unbind"; fr.ina.amalia.player.PlayerMessage.PLUGIN_D3JS_CHART_LABELS = ['Grouped', 'Stacked']; ================================================ FILE: src/ina-player.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * jQuery plugin for ina media player * @function mediaPlayer * @description jQuery media player plugin * @param Object settings settings * @module player */ (function ($) { $.fn.mediaPlayer = function (settings) { return this.each(function () { // The element to display media. var containerElement = $(this); var dataId = 'fr.ina.amalia.player'; // Return early if this element already has a plugin // instance if (containerElement.data(dataId)) { return null; } settings = $.extend({ player: 'default', plugins: {}, src: null, framerate: 25, autoplay: true, controlBarClassName: "fr.ina.amalia.player.plugins.CustomControlBarPlugin", controlBar: {}, tcOffset: 0, mediaType: '', thumbRootDirectory: '', duration: null, togglePlayPause: false, debug: false }, settings || {}); var mediaFactory = new fr.ina.amalia.player.MediaFactory(this, settings); // Store plugin object in this element's data containerElement.data(dataId, mediaFactory); containerElement.addClass('ajs'); containerElement.attr('style', 'width: 100%; height:100%;'); containerElement.parent().css('position', 'relative'); }); }; })(jQuery); ================================================ FILE: src/log/.jshintrc ================================================ { "curly": true, "eqeqeq": true, "immed": true, "latedef": true, "newcap": true, "noarg": true, "sub": true, "undef": true, "unused": true, "boss": true, "eqnull": true, "browser": true, "predef": [ "jQuery", "$", "fr", "console" ] } ================================================ FILE: src/log/log-handler.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * This class provides log utility functions. * @class LogHandler * @namespace fr.ina.amalia.player.log * @constructor * @param {Object} settings Defines the configuration of this class */ $.Class("fr.ina.amalia.player.log.LogHandler", {}, { /** * Defines configuration * @property settings * @type {Object} * @default {} */ settings: {}, init: function (settings) { this.settings = $.extend({ enabled: false }, settings || {}); }, /** * Trace * @method trace * @param {String} className class name * @param {Object} functionName function name * @return {String} Returns log message */ trace: function (className, functionName) { var message = null; if (this.settings.enabled && window.console && window.console.info) { message = className + ":" + functionName; console.info(message); } return message; }, /** * Info * @method info * @param {String|Object} message log message * @return {String|Object} log message */ info: function (message) { var msg = (message) ? message : null; if (this.settings.enabled && window.console && window.console.debug) { console.info(msg); } return msg; }, /** * Error * @method error * @param {String|Object} message log message * @return {String|Object} log message */ error: function (message) { var msg = (message) ? message : null; if (this.settings.enabled && window.console && window.console.error) { console.error(msg); } return msg; }, /** * Warn * @method warn * @param {String|Object} message log message * @return {String|Object} log message */ warn: function (message) { var msg = (message) ? message : null; if (this.settings.enabled && window.console && window.console.warn) { console.warn(msg); } return msg; }, /** * Warn * @method warn * @param {String|Object} message log message * @return {String|Object} log message */ debug: function (message) { var msg = (message) ? message : null; if (this.settings.enabled && window.console && window.console.debug) { console.debug(msg); } return msg; } }); ================================================ FILE: src/player/base-player.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Base class * @class BasePlayer * @module player * @namespace fr.ina.amalia.player * @constructor * @param {Object} settings * @param {Object} mediaContainer */ $.Class("fr.ina.amalia.player.BasePlayer", { mediaPlayerClassCss: "player", mediaPlayerStyleCss: "position: relative; width: inherit; height: inherit; background-color: black; ", playButtonStyleCss: "ajs-icon ajs-icon-controlbar-play", pauseButtonStyleCss: "ajs-icon ajs-icon-controlbar-pause", loaderStyleCss: "ajs-icon ajs-icon-cog" }, { logger: null, settings: {}, /** * Media title * @property title * @type {Object} * @default null */ title: "", /** * Media poster * @property poster * @type {Object} * @default null */ poster: "", /** * Main container * @property mediaContainer * @type {Object} * @default null */ mediaContainer: null, /** * Player instance * @property mediaPlayer * @type {Object} * @default null */ mediaPlayer: null, /** * Plugin manager instance * @property pluginManager * @type {Object} fr.ina.amalia.player.plugins.PluginManager * @default null */ pluginManager: null, /** * Instance of local storage manager. * @property localStorageManager * @type {Object} fr.ina.amalia.player.LocalStorageManager * @default null */ localStorageManager: null, /** * Element to display loader * @property loaderContainer * @type {Object} * @default null */ loaderContainer: null, /** * Element to display play/pause button on screen * @property controlLayerElement * @type {Object} * @default null */ controlLayerElement: null, /** * Element to display error * @property errorContainer * @type {Object} * @default null */ errorContainer: null, /** * True play only range * @property isRangePlayer * @type {Boolean} * @default false */ isRangePlayer: false, /** * Tc for stop player in range mode * @property rangePlayerTcout * @type {Number} * @default null */ rangePlayerTcout: null, /** * Image capture id * @property captureId * @type {Number} * @default null */ captureId: null, /** * Image capture tc * @property captureTc * @type {Number} * @default null */ captureTc: null, /** * Image caputre ratio * @property captureScale * @type {Number} * @default 100 */ captureScale: 1, /** * Zoom tcin * @property zTcin * @type {Number} * @default null */ zTcin: null, /** * Zoom tcout * @property zTcout * @type {Number} * @default null */ zTcout: null, /** * Tc offset * @property tcOffset * @type {Number} * @default 0 */ tcOffset: 0, /** * Media type manager, if your media is not mp4 file. * @property tcOffset * @type {Number} * @default 0 */ mediaTypeManager: null, /** * In charge to manage all metadata * @property metadataManager * @type {Object} * @default null */ metadataManager: null, /** * timeout representing the ID * @property intervalRewind * @type {Object} * @default null */ intervalRewind: null, /** * Shortcut manager * @property shortcutManager * @type {Object} * @default null */ shortcutManager: null, /** * playbackRate speed * @property playbackRate * @type {Number} * @default null */ playbackRateIdx: 7, playbackRateList: [ -2, -1.5, -1, -0.75, -0.5, -0.25, -0.1, 1, 0.5, 0.75, 1.5, 2, 4, 6, 8 ], /** * True if ios devices * @property isIOSDevices * @type {Boolean} * @default false */ isIOSDevices: false, /** * media source url * @property source * @type {Boolean} * @default false */ mediaSourceUrl: "", /** * In Cast Mode * @property inCastMode * @type {Boolean} * @default false */ inCastMode: false, /** * Init player class * @constructor * @param {Object} settings * @param {Object} mediaContainer */ init: function (settings, mediaContainer) { this.controlLayerElement = null; this.mediaSourceUrl = ""; this.inCastMode = false; this.settings = $.extend({ autoplay: false, poster: "", src: "", title: "", defaultVolume: 75, crossorigin: '', shortcuts: {}, defaultPlaybackRateIdx: 7, duration: null }, settings || {}); if (fr.ina.amalia.player.log !== undefined && fr.ina.amalia.player.log.LogHandler !== undefined) { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } this.mediaContainer = mediaContainer; this.setStyleBreakpoint(); this.tcOffset = parseInt(this.settings.tcOffset); this.createLoaderContainer(); if (this.settings.togglePlayPause === true) { this.createControlLayerElement(); } this.createErrorContainer(); this.localStorageManager = new fr.ina.amalia.player.LocalStorageManager({}); this.shortcutManager = new fr.ina.amalia.player.ShortcutsManager(this.settings.shortcuts, this); this.playbackRateIdx = this.settings.defaultPlaybackRateIdx; var IsiPhone = navigator.userAgent.indexOf("iPhone") !== -1; var IsiPod = navigator.userAgent.indexOf("iPod") !== -1; var IsiPad = navigator.userAgent.indexOf("iPad") !== -1; this.isIOSDevices = IsiPhone || IsiPad || IsiPod; this.setTitle(this.settings.title); this.setPoster(this.settings.poster); this.initialize(); }, /** * initialize plugin manager * @method initializePlugins */ initializePlugins: function () { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "initializePlugins"); } this.pluginManager = new fr.ina.amalia.player.plugins.PluginManager(this.settings, this, this.mediaContainer); }, /** * initialize plugin manager * @method initializeMetadataManager */ initializeMetadataManager: function () { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "initializeMetadataManager"); } this.metadataManager = new fr.ina.amalia.player.MetadataManager(this.settings, this, this.mediaContainer); }, /** * In charge to create loader container * @method createLoaderContainer */ createLoaderContainer: function () { this.loaderContainer = $('
', { 'class': 'ajs-loader' }); var loader = $('', { class: this.Class.loaderStyleCss }); this.loaderContainer.append(loader); this.mediaContainer.append(this.loaderContainer); this.showLoader(); }, /** * In charge to create control layer element * @method createControlLayerElement */ createControlLayerElement: function () { this.controlLayerElement = $('
', { 'class': 'ajs-control-layer' }); this.controlLayerElement.append($('')); this.mediaContainer.append(this.controlLayerElement); }, /** * In charge to create error container * @method createErrorContainer */ createErrorContainer: function () { this.errorContainer = $('
', { 'class': 'ajs-error' }); this.errorContainer.hide(); this.mediaContainer.append(this.errorContainer); }, /** * In charge to create error container * @method createErrorContainer */ getContainer: function () { return this.mediaContainer; }, /** * Method in charge to initialize player : - Create containers - Load * plugins * @method initialize */ initialize: function () { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "initialize"); } // plugins this.initializePlugins(); this.initializeMetadataManager(); this.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.INIT, [ this ]); this.getContainer().on(fr.ina.amalia.player.PlayerEventType.ERROR, { self: this }, this.onError); }, /** * In charge to load media * @method load */ load: function () { this.mediaPlayer.get(0).load(); }, /** * In charge to show loader. * @method showControlLayerElement */ showControlLayerElement: function (action) { if (this.controlLayerElement !== null) { var btn = action === "play" ? this.Class.playButtonStyleCss : this.Class.pauseButtonStyleCss; this.controlLayerElement.find('i').attr('class', btn); var self = this; this.controlLayerElement.fadeIn("speed").addClass("scale-up").delay(200).queue(function () { self.controlLayerElement.removeClass("scale-up").fadeOut("speed").dequeue(); }); } }, /** * In charge to show loader. * @method showLoader */ showLoader: function () { this.loaderContainer.show(); }, /** * In charge to hide loader. * @method hideLoader */ hideLoader: function () { this.loaderContainer.hide(); }, /** * return the title of the media * @param {String} title * @method getTitle * @abstract */ getTitle: function () { return this.title; }, /** * Set the title of the media * @param {String} src * @method setSrc * @abstract */ setTitle: function (title) { this.title = title; }, /** * return the cast state * @param {String} inCastMode * @method getCastMode * @abstract */ getCastMode: function () { return this.inCastMode; }, /** * Set the cast state * @param {String} src * @method setCastMode * @abstract */ setCastMode: function (state) { this.inCastMode = state; }, /** * return the title of the media * @param {String} title * @method getTitle * @abstract */ getPoster: function () { return this.poster; }, /** * Set the title of the media * @param {String} src * @method setSrc * @abstract */ setPoster: function (poster) { this.poster = poster; }, /** * In charge to set source * @param {String} src * @param {Boolean} autoplay * @method setSrc * @abstract */ setSrc: function (src, autoplay) { this.mediaSourceUrl = src; if (autoplay === true) { this.play(); } }, /** * In charge to set source * @param {String} src * @param {Boolean} autoplay * @method getSrc * @abstract */ getSrc: function () { return this.mediaSourceUrl; }, /** * Return source content type * @method getContentType * @abstract */ getContentType: function () { return ''; }, /** * In charge to set player events * @method initEvents */ initEvents: function () { // call function 200 ms after resize is complete. $(window).on('debouncedresize', { self: this }, this.onWindowResize); if (this.logger !== null) { this.logger.info("initEvents"); } }, /** * In charge to set style brack point * @method setStyleBreakpoint */ setStyleBreakpoint: function () { var style = 'lg'; var playerWidth = this.mediaContainer.width(); // player width if (playerWidth <= 320) { style = 'xxs'; } else if (playerWidth > 320 && playerWidth <= 480) { style = 'xs'; } else if (playerWidth > 480 && playerWidth <= 768) { style = 'sm'; } else if (playerWidth > 768 && playerWidth <= 992) { style = 'md'; } //Style if (this.mediaContainer.hasClass(style) === false) { this.mediaContainer.removeClass('xxs').removeClass('xs').removeClass('sm').removeClass('md').removeClass('lg').addClass(style); } return style; }, /** * In charge to play media * @method play */ play: function () { this.mediaContainer.addClass('playing-mode').removeClass('paused-mode'); if (typeof this.settings.callbacks.onPlay !== "undefined") { try { /* jslint evil: true */ eval(this.settings.callbacks.onPlay + '()'); } catch (e) { if (this.logger !== null) { this.logger.warn("Send callback failed."); } } } }, /** * In charge to pause media * @method pause */ pause: function () { this.mediaContainer.removeClass('playing-mode').addClass('paused-mode'); this.isRangePlayer = false; this.rangePlayerTcout = null; if (typeof this.settings.callbacks.onPause !== "undefined") { try { /* jslint evil: true */ eval(this.settings.callbacks.onPause + '()'); } catch (e) { if (this.logger !== null) { this.logger.warn("Send callback failed."); } } } }, /** * In charge to stop media * @method stop */ stop: function () { if (this.settings.callbacks.hasOwnProperty("onStop") && typeof this.settings.callbacks.onStop !== "undefined") { try { /* jslint evil: true */ eval(this.settings.callbacks.onStop + '()'); } catch (e) { if (this.logger !== null) { this.logger.warn("Send callback failed."); } } } }, /** * In charge toggle Play * @method stop */ togglePlayPause: function () { if (this.isPaused()) { this.play(); this.showControlLayerElement('play'); } else { this.pause(); this.showControlLayerElement('pause'); } }, /** * In charge to seek * @method seek * @param {Number} time * @return {Number} current time */ seek: function (time) { return this.setCurrentTime(time); }, /** * Set current time to the beginning of the file * @method seekToBegin * @param {Number} time * @return {Number} current time */ seekToBegin: function () { return this.setCurrentTime(0); }, /** * Set current time to the end of the file * @method seekToEnd * @param {Number} time * @return {Number} current time */ seekToEnd: function () { return this.setCurrentTime(this.getDuration()); }, /** * In charge to set mute state * @method mute * @event fr.ina.amalia.player.PlayerEventType.MUTE * @return {Number} */ mute: function () { this.mediaContainer.trigger(fr.ina.amalia.player.PlayerEventType.MUTE); this.mediaContainer.trigger(fr.ina.amalia.player.PlayerEventType.VOLUME_CHANGE, { volume: 0 }); }, /** * In charge to set unmute state * @method unmute * @event fr.ina.amalia.player.PlayerEventType.UN_MUTE */ unmute: function () { this.mediaContainer.trigger(fr.ina.amalia.player.PlayerEventType.UN_MUTE); this.mediaContainer.trigger(fr.ina.amalia.player.PlayerEventType.VOLUME_CHANGE, { volume: 100 }); }, /** * Return true if is mute * @method isMute * @event fr.ina.amalia.player.PlayerEventType.UN_MUTE */ isMute: function () { return this.getVolume() === 0; }, /** * Return player instance * @method muteUnmute * @return {Object} */ muteUnmute: function () { if (this.isMute()) { this.unmute(); } else { this.mute(); } }, /** * Return tc offset * @returns {Number} */ getTcOffset: function () { return this.tcOffset; }, /** * Return player instance * @method getMediaPlayer * @return {Object} */ getMediaPlayer: function () { return this.mediaPlayer; }, /** * Return media duration with tc offset * @method getDuration * @return {Number} */ getDuration: function (duration) { return typeof duration === "number" && isFinite(duration) ? duration : 0; }, /** * Returns the current playback volume percentage, as a number from 0 to * 100. * @method getVolume * @return {Number} */ getVolume: function () { throw new Error("Get volume is abstract method."); }, /** * In charge to play segment * @param {Number} tcin * @param {Number} tcout * @param {Boolean} autoplay true for autolay */ rangePlay: function (tcin, tcout, autoplay) { autoplay = (typeof autoplay === "undefined") ? false : autoplay; this.isRangePlayer = true; this.rangePlayerTcout = tcout + this.tcOffset; this.setCurrentTime(tcin); if (autoplay === true) { this.play(); } }, /** * Sets the player's audio volume percentage, as a number between 0 and 100. * @method setVolume * @param {Number} value */ setVolume: function (value) { if (value >= 0 && value <= 100) { this.mediaContainer.trigger(fr.ina.amalia.player.PlayerEventType.VOLUME_CHANGE, { volume: value }); this.localStorageManager.setItem('volume', value); if (this.logger !== null) { this.logger.trace(this.Class.fullName, "setVolume" + value); } return true; } return false; }, /** * Return current position in seconds * @method getCurrentTime * @return {Number} */ getCurrentTime: function (currentTime) { if (this.settings.duration === null) { return currentTime + this.tcOffset; } else { return this.lastSeekTime + currentTime + this.tcOffset; } }, /** * Set seek position in seconds * @method setCurrentTime * @param {Object} currentTime * @event fr.ina.amalia.player.PlayerEventType.SEEK * @return return current time without tc offset. */ setCurrentTime: function (value) { var currentTime = isNaN(value) ? 0 : value; this.mediaContainer.trigger(fr.ina.amalia.player.PlayerEventType.SEEK, { currentTime: currentTime }); }, /** * Return playback rate * @returns the current playback speed of the audio/video. */ getPlaybackrate: function () { throw new Error("Get volume is abstract method."); }, /** * Set playback rate * @param {Objecy} speed the current playback speed of the audio/video. * @returns the current playback speed of the audio/video. */ setPlaybackrate: function (speed) { throw new Error("Get volume is abstract method. Speed: " + speed); }, upPlaybackrate: function () { this.playbackRateIdx = Math.min(this.playbackRateList.length, this.playbackRateIdx + 1); this.setPlaybackrate(parseInt(this.playbackRateList[this.playbackRateIdx])); }, downPlaybackrate: function () { this.playbackRateIdx = Math.max(0, this.playbackRateIdx - 1); this.setPlaybackrate(parseInt(this.playbackRateList[this.playbackRateIdx])); }, /** * Set Error * @method setErrorCode * @param {Object} errorCode */ setErrorCode: function (errorCode) { if (typeof this.errorContainer !== "undefined") { var messageContainer = $('

', { text: fr.ina.amalia.player.PlayerErrorCode.getMessage(errorCode) }); this.errorContainer.html(messageContainer); this.errorContainer.show(); } }, /** * Returns the current fullscreen state * @method getFullscreenState * @return {Boolean} description */ getFullscreenState: function () { throw new Error("Get fullscreen is abstract method."); }, /** * Return true if media is paused * @method isPaused * @return {Boolean} */ isPaused: function () { throw new Error("Is paused is abstract method."); }, /** * In charge to toggle full-screen state * @see HTML5 Fullscreen API * @method toggleFullScreen * @return {Boolean} true */ toggleFullScreen: function (inFullScreen) { var container = (this.isIOSDevices) ? this.mediaPlayer.get(0) : this.mediaContainer.get(0); var iFS = fr.ina.amalia.player.helpers.HTML5Helper.toggleFullScreen(container, this.isIOSDevices); if (typeof this.settings.callbacks.onFullscreen !== "undefined") { try { /* jslint evil: true */ eval(this.settings.callbacks.onFullscreen + '(inFullScreen)'); } catch (e) { if (this.logger !== null) { this.logger.warn("Send callback failed."); } } } if (this.logger !== null) { this.logger.trace(this.Class.fullName, "onClickFullscreenButton :" + inFullScreen); } return iFS; }, /** * Returns the current fullscreen state * @method getFullscreenState * @return {Boolean} description */ getContentTupe: function () { throw new Error("Get media content type is abstract method."); }, /** * Return current image * @param {Nomber} scale max 1=> 100% * @method getCurrentImage * @event fr.ina.amalia.player.PlayerEventType.IMAGE_CAPTURE */ getCurrentImage: function (scale) { throw new Error("Get currentTime is abstract method. Scale: " + scale); }, /** * Return current image for specified time code. * @param {String} id * @param {Number} tc * @param {Number} scale max 1=> 100% * @method getTcImage * @event fr.ina.amalia.player.PlayerEventType.IMAGE_CAPTURE */ getTcImage: function (id, tc, scale) { this.setCurrentTime(tc); // Need to call player for make capture this.play(); this.captureId = id; this.captureTc = tc + this.tcOffset; this.captureScale = (typeof scale !== 'undefined') ? Math.min(1, parseFloat(scale)) : 1; }, /** * In charge to move next frame * @method moveNextFrame * @param {Object} event */ moveNextFrame: function () { this.pause(); this.setCurrentTime(Math.min(this.getDuration() + this.tcOffset, this.getCurrentTime() + (1 / this.settings.framerate))); }, /** * In charge to move prev frame * @method movePrevFrame * @param {Object} event */ movePrevFrame: function () { this.pause(); this.setCurrentTime(Math.max(0, this.getCurrentTime() - (1 / this.settings.framerate))); }, /** * In charge to add menu context item * @param {String} title * @param {String} link * @param {String} className */ addMenuItemWithLink: function (title, link, className) { if (typeof this.pluginManager === "object" && typeof this.pluginManager.getContextMenuPlugin === "function") { var contextMenuPlugin = this.pluginManager.getContextMenuPlugin(); if (typeof contextMenuPlugin === "object" && typeof contextMenuPlugin.addItemWithLink === "function") { return contextMenuPlugin.addItemWithLink(title, link, className); } } return false; }, /** Metadata **/ /** * Return instance of metadata manager */ getMetadataManager: function () { return this.metadataManager; }, /** * Return all block of metadata */ getBlocksMetadata: function () { return this.metadataManager.getBlocksMetadata(); }, /** * Return the block of metadata by id */ getBlockMetadata: function (id) { return this.metadataManager.getBlockMetadata(id); }, /** * Update the block metadata */ updateBlockMetadata: function (id, data, action) { this.metadataManager.updateBlockMetadata(id, data, action); }, /** * Remove the block metadata with id metadata */ removeBlockMetadata: function (id) { return this.metadataManager.removeBlockMetadata(id); }, /** * In charge to add metadata, it is called by metadata parser * @method addAllMetadata * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ addAllMetadata: function (parsedData) { this.metadataManager.addAllMetadata(parsedData); }, /** * In charge to return metadata by id * @method addMetadataById * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ addMetadataById: function (id, parsedData) { this.metadataManager.addMetadataById(id, parsedData); }, /** * In charge to replace metadata by id * @method replaceAllMetadataById * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ replaceAllMetadataById: function (id, parsedData) { this.metadataManager.replaceAllMetadataById(id, parsedData); }, /** * In charge to delete metadata by id * @method deleteAllMetadataById * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ deleteAllMetadataById: function (id) { this.metadataManager.deleteAllMetadataById(id); }, /** * Return metadata by id * @method getMetadataById * @param {String} id * @return {Array} */ getMetadataById: function (id) { return this.metadataManager.getMetadataById(id); }, /** * Set metadata by id * @method setMetadataById * @param {String} id * @param {Object} data * @return {Array} */ setMetadataById: function (id, data) { return this.metadataManager.setMetadataById(id, data); }, /** * In charge to remove metadata * @method removeMetadataById */ removeMetadataById: function (id) { return this.metadataManager.removeMetadataById(id); }, /** * Return a metadata by specified time code. * @method getMetadataWithRange * @param id * @param tcin * @param tcout * @return {Array} */ getMetadataWithRange: function (id, tcin, tcout) { return this.metadataManager.getMetadataWithRange(id, tcin, tcout); }, /** * Return selected component id * @method getSelectedMetadataId */ getSelectedMetadataId: function () { return this.metadataManager.getSelectedMetadataId(); }, /** * Set selected component id * @method setSelectedMetadataId */ setSelectedMetadataId: function (metadataId) { this.metadataManager.setSelectedMetadataId(metadataId); }, /** * In charge to add metadata item * @method addMetadataItem */ addMetadataItem: function (metadataId, data) { return this.metadataManager.addMetadataItem(metadataId, data); }, /** * Return selected items */ getSelectedItems: function () { return this.metadataManager.getSelectedItems(); }, /** * Add selected item */ addSelectedItem: function (item) { this.metadataManager.addSelectedItem(item); }, /** * Remove all selected items */ removeAllSelectedItems: function () { this.metadataManager.removeAllSelectedItems(); }, /** * Return tcin with tc offset * @returns {Number} */ getTcin: function () { return this.getTcOffset(); }, /** * Return Tcout with tcoffset and media duration * @returns {Number} */ getTcout: function () { return this.getTcOffset() + this.getDuration(); }, /** * In charge to set zoom tc * @param {Number} zTcin * @param {Number} zTcout * @param {String} eventTag */ setZoomTc: function (zTcin, zTcout, eventTag) { eventTag = (typeof eventTag !== 'undefined') ? eventTag : ''; if (Math.ceil(this.zTcin) !== Math.ceil(zTcin) || Math.ceil(this.zTcout) !== Math.ceil(zTcout)) { this.zTcin = Math.max(0, parseFloat(zTcin)); this.zTcout = parseFloat(zTcout); if (this.logger !== null) { this.logger.info("SetZoomTc: // Tcin: " + this.zTcin + " // Tcout:" + this.zTcout + " // Event Tag Name:" + eventTag); } this.mediaContainer.trigger(fr.ina.amalia.player.PlayerEventType.ZOOM_RANGE_CHANGE, { zTcin: parseFloat(zTcin), zTcout: parseFloat(zTcout), eventTag: eventTag }); } }, /** * In Charge to remove instance */ destroy: function () { //Fix clear socket this.setSrc("", false); if (typeof this.mediaContainer.data("fr.ina.amalia.player") !== "undefined") { this.mediaContainer.data("fr.ina.amalia.player", null); } //clear html content this.mediaContainer.get(0).innerHTML = ""; this.mediaContainer.remove(); }, /** * Fired on player has errors. * @method onError * @param {Object} event * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.ERROR */ onError: function (event, data) { if (event.data.self.logger !== null) { event.data.self.logger.trace(event.data.self.Class.fullName, "onError"); } var errorCode = (typeof data.errorCode === "undefined") ? '' : data.errorCode; event.data.self.setErrorCode(errorCode); if (typeof event.data.self.settings.callbacks.onError !== "undefined") { try { /* jslint evil: true */ eval(event.data.self.settings.callbacks.onError + '(errorCode)'); } catch (e) { if (event.data.self.logger !== null) { event.data.self.logger.warn("Send callback failed."); } } } }, /** * Fired on windows resize * @method onWindowResize * @param {Object} event */ onWindowResize: function (event) { event.data.self.setStyleBreakpoint(); if (event.data.self.logger !== null) { event.data.self.logger.trace(event.data.self.Class.fullName, "onWindowResize"); } } }); ================================================ FILE: src/player/constants/player-error-code.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Collected of player error code * @class PlayerErrorCode * @namespace fr.ina.amalia.player * @module player * @submodule player-constants */ $.Class("fr.ina.amalia.player.PlayerErrorCode", { /** * @constant * @property ACCESS_DENIED * @type {Number} */ ACCESS_DENIED: 1001, /** * @constant * @property MEDIA_FILE_NOT_FOUND * @type {Number} */ MEDIA_FILE_NOT_FOUND: 2001, /** * @constant * @property CUSTOM_ERROR * @type {Number} */ CUSTOM_ERROR: 3001, /** * @constant * @property EXCEPTION * @type {Number} */ EXCEPTION: 4001, /** * @constant * @property HTTP_ERROR * @type {Number} */ HTTP_ERROR: 5001, /** * @constant * @property ABORT * @type {Number} */ ABORT: 6001, /** * @constant * @property TIMEOUT * @type {Number} */ TIMEOUT: 7008, /** * @constant * @property ERROR * @type {Number} */ ERROR: 8008, /** * @constant * @property ERROR_HTML5_SUPPORT * @type {Number} */ ERROR_HTML5_SUPPORT: 8000, /** * @constant * @property ERROR_LOAD_PLUGIN * @type {Number} */ ERROR_LOAD_PLUGIN: 9001, /** * @constant * @property ERROR_MANIFEST_DASH * @type {Number} */ ERROR_MANIFEST_DASH: 9002, /** * Return message by code error * @param {Number} errorCode * @returns {String} Return message */ getMessage: function (errorCode) { var CodeClass = fr.ina.amalia.player.PlayerErrorCode; var MessageClass = fr.ina.amalia.player.PlayerErrorMessage; switch (errorCode) { case CodeClass.ACCESS_DENIED : return MessageClass.ACCESS_DENIED; case CodeClass.MEDIA_FILE_NOT_FOUND : return MessageClass.MEDIA_FILE_NOT_FOUND; case CodeClass.EXCEPTION : return MessageClass.EXCEPTION; case CodeClass.HTTP_ERROR : return MessageClass.HTTP_ERROR; case CodeClass.ABORT : return MessageClass.ABORT; case CodeClass.TIMEOUT : return MessageClass.TIMEOUT; case CodeClass.ERROR_LOAD_PLUGIN : return MessageClass.ERROR_LOAD_PLUGIN; case CodeClass.CUSTOM_ERROR : return MessageClass.CUSTOM_ERROR; case CodeClass.ERROR : return MessageClass.ERROR; case CodeClass.ERROR_HTML5_SUPPORT : return MessageClass.ERROR_HTML5_SUPPORT; case CodeClass.ERROR_MANIFEST_DASH: return MessageClass.ERROR_MANIFEST_DASH; default : return MessageClass.DEFAULT; } } }, {}); /** * Constant class for error message * @class PlayerErrorMessage: * @namespace fr.ina.amalia.player * @module player * @submodule player-constants */ $.Class("fr.ina.amalia.player.PlayerErrorMessage", { ACCESS_DENIED: 'Accès refusé.', MEDIA_FILE_NOT_FOUND: 'Erreur lors du chargement du média.', EXCEPTION: 'An exception occurred.', HTTP_ERROR: 'Http response at 400 or 500 level.', ABORT: 'Votre requête a été interrompue.', TIMEOUT: 'Demande dépassé.', ERROR_LOAD_PLUGIN: 'Erreur inattendue lors de l\'initialisation du plug-in.', CUSTOM_ERROR: 'Une erreur s\'est produite sur votre lecteur.', ERROR: 'Une erreur s\'est produite sur votre lecteur.', DEFAULT: 'Une erreur s\'est produite sur votre lecteur.', ERROR_HTML5_SUPPORT: 'Une erreur s\'est produite sur votre lecteur: Votre navigateur ne gère pas les balises HTML5.', ERROR_MANIFEST_DASH: 'Erreur lors du chargement du manifest dash' }, {}); ================================================ FILE: src/player/constants/player-event-type.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Player event type * @class PlayerEventType * @namespace fr.ina.amalia.player * @module player * @submodule player-constants */ $.Class("fr.ina.amalia.player.PlayerEventType", { /** * Fired when the player has initialized. * @constant * @property INIT * @type {String} */ INIT: "fr.ina.amalia.player.PlayerEventType.INIT", /** * Fired when the player has started with duration. * @constant * @property STARTED * @type {String} */ STARTED: "fr.ina.amalia.player.PlayerEventType.STARTED", /** * Fires when playing event. * @constant * @property PLAYING * @type {String} */ CAST_PLAYING: "fr.ina.amalia.player.PlayerEventType.CAST_PLAYING", /** * Fires the paused/resumed * @constant * @property PAUSED * @type {String} */ CAST_PAUSED: "fr.ina.amalia.player.PlayerEventType.CAST_PAUSED", /** * Fires when playing event. * @constant * @property PLAYING * @type {String} */ PLAYING: "fr.ina.amalia.player.PlayerEventType.PLAYING", /** * Fires the paused/resumed * @constant * @property PAUSED * @type {String} */ PAUSED: "fr.ina.amalia.player.PlayerEventType.PAUSED", /** * Ended event should fire when a video is completely. * @constant * @property ENDED * @type {String} */ ENDED: "fr.ina.amalia.player.PlayerEventType.ENDED", /** * This fires when the volume level is equal to 0. * @constant * @property MUTE * @type {String} */ MUTE: "fr.ina.amalia.player.PlayerEventType.MUTE", /** * This fires when the volume level is equal to 0. * @constant * @property UN_MUTE * @type {String} */ UN_MUTE: "fr.ina.amalia.player.PlayerEventType.UN_MUTE", /** * This fires when the volume level is changed. * @constant * @property UN_MUTE * @type {String} */ VOLUME_CHANGE: "fr.ina.amalia.player.PlayerEventType.VOLUME_CHANGE", /** * This fires when the time change with attributes : 'obj' : instance of * player 'currentTime' : player currentTime 'duration' : media duration * 'percent' * @constant * @property TIME_CHANGE * @type {String} */ TIME_CHANGE: "fr.ina.amalia.player.PlayerEventType.TIME_CHANGE", /** * This fires when full-screen mode change * @constant * @property FULLSCREEN_CHANGE * @type {String} */ FULLSCREEN_CHANGE: "fr.ina.amalia.player.PlayerEventType.FULLSCREEN_CHANGES", /** * Fired when the user seeks. * @constant * @property SEEK * @type {String} */ SEEK: "fr.ina.amalia.player.PlayerEventType.SEEK", /** * Fired when a media error has occurred. * @constant * @property ERROR * @type {String} */ ERROR: "fr.ina.amalia.player.PlayerEventType.ERROR", /** * Fired when the player has initialized. * @constant * @property PLUGIN_READY * @type {String} * @deprecated */ PLUGIN_READY: "fr.ina.amalia.player.PlayerEventType.PLUGIN_READY", /** * Fired when a plugin error has occurred. * @constant * @property PLUGIN_ERROR * @type {String} */ PLUGIN_ERROR: "fr.ina.amalia.player.PlayerEventType.PLUGIN_ERROR", /** * Fired when data change * @constant * @property PLUGIN_ERROR * @type {String} */ DATA_CHANGE: "fr.ina.amalia.player.PlayerEventType.DATA_CHANGE", /** * Fired at the beginning of data change * @constant * @property BEGIN_DATA_CHANGE * @type {String} */ BEGIN_DATA_CHANGE: "fr.ina.amalia.player.PlayerEventType.BEGIN_DATA_CHANGE", /** * Fired end of data change * @constant * @property END_DATA_CHANGE * @type {String} */ END_DATA_CHANGE: "fr.ina.amalia.player.PlayerEventType.END_DATA_CHANGE", /** * Fired when image capture * @constant * @property IMAGE_CAPTURE * @type {String} */ IMAGE_CAPTURE: "fr.ina.amalia.player.PlayerEventType.IMAGE_CAPTURE", /** * Fired when zoom range change * @constant * @property ZOOM_RANGE_CHANGE * @type {String} */ ZOOM_RANGE_CHANGE: "fr.ina.amalia.player.PlayerEventType.ZOOM_RANGE_CHANGE", /** * Fired when selected metadata has changed * @constant * @property SELECTED_METADATA_CHANGE * @type {String} */ SELECTED_METADATA_CHANGE: "fr.ina.amalia.player.PlayerEventType.SELECTED_METADATA_CHANGE", /** * Fired when selected item has changed * @constant * @property SELECTED_ITEMS_CHANGE * @type {String} */ SELECTED_ITEMS_CHANGE: "fr.ina.amalia.player.PlayerEventType.SELECTED_ITEMS_CHANGE", /** * Fired when bind metadata * @constant * @property BIND_METADATA * @type {String} */ BIND_METADATA: "fr.ina.amalia.player.PlayerEventType.BIND_METADATA", /** * Fired when unbind metadata * @constant * @property UNBIND_METADATA * @type {String} */ UNBIND_METADATA: "fr.ina.amalia.player.PlayerEventType.UNBIND_METADATA", /** * Fired when unbind metadata * @constant * @property PLAYBACK_RATE_CHANGE * @type {String} */ PLAYBACK_RATE_CHANGE: "fr.ina.amalia.player.PlayerEventType.PLAYBACK_RATE_CHANGE", /** * Fired when Stop Seeking * @constant * @property START_SEEKING * @type {String} */ START_SEEKING: "fr.ina.amalia.player.PlayerEventType.START_SEEKING", /** * Fired when Stop Seeking * @constant * @property STOP_SEEKING * @type {String} */ STOP_SEEKING: "fr.ina.amalia.player.PlayerEventType.STOP_SEEKING", /** * Fired when seeking * @constant * @property SEEKING * @type {String} */ SEEKING: "fr.ina.amalia.player.PlayerEventType.SEEKING" }, {}); ================================================ FILE: src/player/constants/player-message.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Constant message class * @class PlayerMessage * @namespace fr.ina.amalia.player * @module player * @submodule player-constants */ $.Class("fr.ina.amalia.player.PlayerMessage", { /** * @constant * @property PLAYER_OPENSOURCE_LINK * @type {String} */ PLAYER_OPENSOURCE_LINK: 'Disponibles en open source.', /** * @constant * @property PLUGIN_OVERLAY_CONTEXT_MENU_ENABLED_DISABLED_PLUGIN * @type {String} */ PLUGIN_OVERLAY_CONTEXT_MENU_ENABLED_DISABLED_PLUGIN: 'Activer/désactiver le plugin overlay.', /** * @constant * @property PLUGIN_TIMELINE_LABEL_ELEMENTS * @type {String} */ PLUGIN_TIMELINE_LABEL_ELEMENTS: "éléments.", /** * @constant * @property PLUGIN_TIMELINE_LABEL_ZOOM_IN * @type {String} */ PLUGIN_TIMELINE_LABEL_ZOOM_IN: "Zoom avant", /** * @constant * @property PLUGIN_TIMELINE_LABEL_ZOOM_OUT * @type {String} */ PLUGIN_TIMELINE_LABEL_ZOOM_OUT: "Zoom arrière", /** * @constant * @property PLUGIN_TIMELINE_LABEL_CHANGE_DISPLAY * @type {String} */ PLUGIN_TIMELINE_LABEL_CHANGE_DISPLAY: "Changer la hauteur des lignes.", /** * @constant * @property PLUGIN_TIMELINE_LABEL_SLIDE_LEFT * @type {String} */ PLUGIN_TIMELINE_LABEL_SLIDE_LEFT: "Faire défiler vers la gauche", /** * @constant * @property PLUGIN_TIMELINE_LABEL_SLIDE_RIGHT * @type {String} */ PLUGIN_TIMELINE_LABEL_SLIDE_RIGHT: "Faire défiler vers la droite", /** * @constant * @property PLUGIN_TIMELINE_LABEL_SCROLL_UP * @type {String} */ PLUGIN_TIMELINE_LABEL_SCROLL_UP: "Faire défiler vers le haut", /** * @constant * @property PLUGIN_TIMELINE_LABEL_SCROLL_DOWN * @type {String} */ PLUGIN_TIMELINE_LABEL_SCROLL_DOWN: "Faire défiler vers le bas", /** * @constant * @property PLUGIN_TIMELINE_LABEL_SHOW_HIDE_TOOTIP * @type {String} */ PLUGIN_TIMELINE_LABEL_SHOW_HIDE_TOOTIP: "Activer/désactiver les infobulles", /** * @constant * @property PLUGIN_TIMELINE_LABEL_EXPAND * @type {String} */ PLUGIN_TIMELINE_LABEL_EXPAND: "Maximiser / Minimiser", /** * @constant * @property PLUGIN_TIMELINE_LABEL_SORT * @type {String} */ PLUGIN_TIMELINE_LABEL_SORT: "Trier", /** * @constant * @property PLUGIN_TIMELINE_LABEL_NAV_POINT_PREV * @type {String} */ PLUGIN_TIMELINE_LABEL_NAV_POINT_PREV: "Aller au marqueur précédent", /** * @constant * @property PLUGIN_TIMELINE_LABEL_NAV_POINT_NEXT * @type {String} */ PLUGIN_TIMELINE_LABEL_NAV_POINT_NEXT: "Aller au marqueur suivant", /** * @constant * @property PLUGIN_TIMELINE_LABEL_TIMEAXIS * @type {String} */ PLUGIN_TIMELINE_LABEL_TIMEAXIS: "Axe temporel", /** * @constant * @property PLUGIN_TIMELINE_LABEL_FOCUS * @type {String} */ PLUGIN_TIMELINE_LABEL_FOCUS: "Zoom", /** * @constant * @property PLUGIN_TIMELINE_LABEL_CLOSE * @type {String} */ PLUGIN_TIMELINE_LABEL_CLOSE: "Fermer", /** * @constant * @property PLUGIN_METADATA_LIST_EDITOR_LABEL_HEADER * @type {String} */ PLUGIN_METADATA_LIST_EDITOR_LABEL_HEADER: "Metadata list editor", /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_LABEL_HEADER * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_LABEL_HEADER: "Metadata block editor", /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_LABEL_HEADER * @type {String} */ PLUGIN_METADATA_ITEMS_EDITOR_LABEL_HEADER: "Metadata items editor", /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_ID * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_ID: "ID", /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_LABAL * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_LABAL: 'Etiquette', /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_TYPE * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_TYPE: 'Type', /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_TYPE * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_DESCRIPTION: 'Description', /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_TYPE * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_REFERENCE: 'Référence', /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_AUTHOR * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_AUTHOR: 'Auteur', /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_SHAPE * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_SHAPE: 'Forme', /** * @constant * @property PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_COLOR * @type {String} */ PLUGIN_METADATA_BLOCK_EDITOR_FORM_LABEL_METADATA_COLOR: 'Couleur', /** * @constant * @property PLUGIN_METADATA_ITEMS_EDITOR_NEED_METADTA * @type {String} */ PLUGIN_METADATA_ITEMS_EDITOR_NEED_METADTA: 'Vous devez sélectionner au moins un élément dans la liste des métadonnées avant de l\'ajouter élément.', /** * @constant * @property PLUGIN_METADATA_ITEMS_EDITOR_NEED_METADTA_ITEM_TYPE * @type {String} */ PLUGIN_METADATA_ITEMS_EDITOR_NEED_METADTA_ITEM_TYPE: 'Vous devez définir le type élément.', /** * @constant * @property PLUGIN_TIMELINE_LABEL_BIND * @type {String} */ PLUGIN_TIMELINE_LABEL_BIND: "Attacher/Detacher", /** * @constant * @property PLUGIN_TIMELINE_LABEL_BIND * @type {String} */ PLUGIN_D3JS_CHART_LABELS: ['Groupés', 'Empilés'] }, {}); ================================================ FILE: src/player/loader/base-loader.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * In charge to load data * @class LoaderBase * @namespace fr.ina.amalia.player * @module player * @constructor * @param {Object} parameter * @param {Object} mediaContainer * @param {Object} handlerData */ $.Class("fr.ina.amalia.player.BaseLoader", {}, { /** * Defines configuration * @property settings * @type {Object} * @default {} */ settings: {}, /** * In charge to render messages in the web console output * @property logger * @type {Object} * @default null */ logger: null, /** * Loaded data * @property logger * @type {Object} * @default null */ data: null, /** * load handler function * @property logger * @type {Object} * @default null */ handlerData: {}, /** * complete handler function * @property logger * @type {Object} * @default null */ completeHandler: null, /** * Instance of player * @property player * @type {Object} * @default null */ player: null, /** * Wait load event * @property player * @type {Object} * @default null */ waitLoadEvent: false, /** * Instance of parser class * @property player * @type {Object} * @default null */ parser: null, /** * Init this class * @constructor * @method init * @param {Object} settings */ init: function (settings, player, completeHandler, handlerData) { this.settings = $.extend({ debug: false, sublocalisations: false }, settings || {}); this.player = player; this.parser = null; this.handlerData = $.extend({ debug: false }, handlerData || {}); this.completeHandler = completeHandler; this.logger = null; if (typeof fr.ina.amalia.player.log !== "undefined" && typeof fr.ina.amalia.player.log.LogHandler !== "undefined") { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } this.initialize(); }, /** * initialize * @constructor * @method initialize */ initialize: function () { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "initialize"); } this.initializeParser(); }, /** * In charge to instantiate parser * @method processFilterData * @param {Object} data */ initializeParser: function () { this.parser = null; if (this.settings.format === 'json') { this.parser = new fr.ina.amalia.player.parsers.BaseParserMetadata(this.settings); } else { try { // In charge to instantiate parser custom class /* jslint evil: true */ this.parser = eval('new ' + this.settings.format + '(this.settings)'); } catch (error) { this.parser = null; if (this.logger !== null) { this.logger.warn("Unknown host configuration type."); this.logger.error(error.stack); } } } }, /** * Set request type * @method setRequestType */ setRequestType: function (requestType) { this.requestType = requestType; }, /** * Set data type * @method setDataType */ setDataType: function (dataType) { this.dataType = dataType; }, /** * Set time out value * @method setTimeout */ setTimeout: function (timeout) { this.timeout = timeout; }, /** * Set send data * @method setSendData */ setSendData: function (data) { this.sendData = $.extend(this.sendData, data || {}); }, /** * Get send data * @method getSendData */ getSendData: function () { return this.sendData; }, /** * Return wait load state * @method getSendData */ getWaitLoadEvent: function () { return this.waitLoadEvent; }, /** * Get loaded data * @method initialize */ getData: function () { return this.data; }, /** * On success * @method onSuccess * @param {Object} data * @param {String} textStatus */ onSuccess: function (data, textStatus) { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "onSuccess status: " + textStatus); } }, /** * onError * @method onError * @param {Object} textStatus */ onError: function (textStatus) { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "onError status :" + textStatus); } } }); ================================================ FILE: src/player/loader/http-loader.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * In charge to http loader * @class LoaderHTTP * @namespace fr.ina.amalia.player * @module player */ fr.ina.amalia.player.BaseLoader.extend("fr.ina.amalia.player.HttpLoader", {}, { /** * Load data request type * @property requestType * @type {String} * @default 'GET' */ requestType: 'GET', /** * Load data type * @property logger * @type {String} * @default 'json' */ dataType: 'json', /** * Send data object * @property sendData * @type {Object} * @default null */ sendData: {}, /** * call time out * @property timeout * @type {Number} * @default null */ timeout: 120000, init: function (settings, player, completeHandler, handlerData) { this._super(settings, player, completeHandler, handlerData); this.waitLoadEvent = true; }, /** * initialize * @constructor * @method initialize */ initialize: function () { this._super(); this.load(this.settings.url); }, /** * Load http service * @method load * @param {Object} url */ load: function (url) { var self = this; $.ajax({ type: this.requestType, url: url, timeout: this.timeout, data: this.sendData, dataType: this.dataType, success: function (data, textStatus) { self.onSuccess(data, textStatus); }, error: function (data, textStatus) { self.onError(textStatus); } }); if (this.logger !== null) { this.logger.trace(this.Class.fullName, "Load url :" + url); } }, /** * On success * @method onSuccess * @param {Object} data * @param {String} textStatus */ onSuccess: function (data, textStatus) { this._super(data, textStatus); this.data = null; if (this.parser !== null) { this.data = this.parser.processParserData(data); this.player.addAllMetadata(this.data); } if (typeof this.completeHandler === 'function') { this.completeHandler(this.handlerData, textStatus); } }, /** * onError * @method onError * @param {Object} textStatus */ onError: function (textStatus) { this._super(textStatus); this.data = null; if (typeof this.completeHandler === 'function') { this.completeHandler(this.handlerData, textStatus); } } }); ================================================ FILE: src/player/loader/ws-loader.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * In charge to web socket loader * @class LoaderHTTP * @namespace fr.ina.amalia.player * @module player */ fr.ina.amalia.player.BaseLoader.extend("fr.ina.amalia.player.WsLoader", {}, { /** * Defines configuration * @property socket * @type {Object} * @default null */ socket: null, listOfMetadata: null, init: function (settings, player, completeHandler, handlerData) { this._super(settings, player, completeHandler, handlerData); this.waitLoadEvent = false; }, /** * initialize * @constructor * @method initialize */ initialize: function () { this._super(); this.socket = null; this.listOfMetadata = []; this.connect(this.settings.url); this.player.getContainer().on(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { self: this }, this.onPlayerDataChange); }, /** * In charge to create a new WebSocket */ connect: function (url) { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "Load url :" + url); } // creates a new WebSocket if (typeof WebSocket === "function") { this.socket = new WebSocket(url); if (this.socket !== null) { $(this.socket).on('open', { self: this }, this.onOpen).on('close', { self: this }, this.onClose).on('message', { self: this }, this.onMessage).on('error', { self: this }, this.onError); } } else { if (this.logger !== null) { this.logger.error('Error: WebSocket is not supported by this browser or the server is not started.'); } } }, /** * This event occurs when socket connection is established * @method onOpen * @param {Object} */ onOpen: function (event) { if (event.data.self.logger !== null) { event.data.self.logger.trace(event.data.self.Class.fullName, 'WebSocket connection opened'); } }, /** * This event occurs when connection is closed. * @method onClose * @param {Object} */ onClose: function (event) { event.data.self.socket = null; if (event.data.self.logger !== null) { event.data.self.logger.trace(event.data.self.Class.fullName, 'WebSocket connection closed'); } }, /** * This event occurs when client receives data from server. * @method onMessage * @param {Object} event */ onMessage: function (event) { try { //recived data var jsonData = JSON.parse(event.originalEvent.data); event.data.self.data = event.data.self.parser.processParserData(jsonData); var viewControl = event.data.self.data.viewControl; var action = (event.data.self.data.viewControl !== null && event.data.self.data.viewControl.hasOwnProperty('action')) ? event.data.self.data.viewControl.action : ''; //action if (event.data.self.data !== null) { switch (action) { case 'add-all' : event.data.self.player.updateBlockMetadata(event.data.self.data.id, { id: event.data.self.data.id, label: event.data.self.data.label, type: event.data.self.data.hasOwnProperty('type') ? event.data.self.data.type : 'default', author: (viewControl !== null && viewControl.hasOwnProperty('author')) ? viewControl.author : '', color: (viewControl !== null && viewControl.hasOwnProperty('color')) ? viewControl.color : '#3cf', shape: (viewControl !== null && viewControl.hasOwnProperty('shape') && viewControl.shape !== "") ? viewControl.shape : 'circle' }, null); event.data.self.player.addMetadataById(event.data.self.data.id, event.data.self.data.list); break; case 'replace-all' : event.data.self.player.updateBlockMetadata(event.data.self.data.id, { id: event.data.self.data.id, label: event.data.self.data.label, type: event.data.self.data.hasOwnProperty('type') ? event.data.self.data.type : 'default', author: (viewControl !== null && viewControl.hasOwnProperty('author')) ? viewControl.author : '', color: (viewControl !== null && viewControl.hasOwnProperty('color')) ? viewControl.color : '#3cf', shape: (viewControl !== null && viewControl.hasOwnProperty('shape') && viewControl.shape !== "") ? viewControl.shape : 'circle' }, action); event.data.self.player.replaceAllMetadataById(event.data.self.data.id, event.data.self.data.list); break; case 'delete-all' : event.data.self.player.deleteAllMetadataById(event.data.self.data.id); break; default : event.data.self.player.updateBlockMetadata(event.data.self.data.id, { id: event.data.self.data.id, label: event.data.self.data.label, type: event.data.self.data.hasOwnProperty('type') ? event.data.self.data.type : 'default', author: (viewControl !== null && viewControl.hasOwnProperty('author')) ? viewControl.author : '', color: (viewControl !== null && viewControl.hasOwnProperty('color')) ? viewControl.color : '#3cf', shape: (viewControl !== null && viewControl.hasOwnProperty('shape') && viewControl.shape !== "") ? viewControl.shape : 'circle' }, null); event.data.self.player.addMetadataById(event.data.self.data.id, event.data.self.data.list); } } } catch (e) { // Exception SyntaxError event.data.self.data = null; if (event.data.self.logger !== null) { event.data.self.logger.error("Error to add metadata"); event.data.self.logger.error(event.originalEvent.data); } } }, /** * This event occurs when there is any error in communication. * @method onError * @param {Object} event */ onError: function (event) { event.data.self.socket = null; event.data.self.data = null; if (event.data.self.logger !== null) { event.data.self.logger.error("Error to initialize, web socket connection."); event.data.self.logger.error(event); } }, /** * This event occurs when data change event * @method onPlayerDataChange * @param {Object} event * @param {Object} data */ onPlayerDataChange: function (event, data) { if (event.data.self.logger !== null) { event.data.self.logger.trace(event.data.self.Class.fullName, 'onPlayerDataChange'); event.data.self.logger.debug(event); event.data.self.logger.debug(event.data.self.player.getMetadataById(data.id)); } } }); ================================================ FILE: src/player/loaderBase.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * In charge to load data * @class LoaderBase * @namespace fr.ina.amalia.player * @module player * @constructor * @param {Object} parameter * @param {Object} mediaContainer * @param {Object} handlerData */ $.Class("fr.ina.amalia.player.LoaderBase", {}, { /** * Defines configuration * @property settings * @type {Object} * @default {} */ settings: {}, /** * In charge to render messages in the web console output * @property logger * @type {Object} * @default null */ logger: null, /** * Load data request type * @property requestType * @type {String} * @default 'GET' */ requestType: 'GET', /** * Load data type * @property logger * @type {String} * @default 'json' */ dataType: 'json', /** * Send data object * @property sendData * @type {Object} * @default null */ sendData: {}, /** * call time out * @property timeout * @type {Number} * @default null */ timeout: 120000, /** * Loaded data * @property logger * @type {Object} * @default null */ data: null, /** * load handler function * @property logger * @type {Object} * @default null */ handlerData: {}, /** * complete handler function * @property logger * @type {Object} * @default null */ completeHandler: null, /** * Init this class * @constructor * @method init * @param {Object} settings */ init: function (settings, completeHandler, handlerData) { this.settings = $.extend({ debug: false }, settings || {}); this.handlerData = $.extend({ debug: false }, handlerData || {}); this.completeHandler = completeHandler; if (typeof fr.ina.amalia.player.log !== "undefined" && typeof fr.ina.amalia.player.log.LogHandler !== "undefined") { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } this.initialize(); }, /** * initialize * @constructor * @method initialize */ initialize: function () { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "initialize"); } }, /** * Set request type * @method setRequestType */ setRequestType: function (requestType) { this.requestType = requestType; }, /** * Set data type * @method setDataType */ setDataType: function (dataType) { this.dataType = dataType; }, /** * Set time out value * @method setTimeout */ setTimeout: function (timeout) { this.timeout = timeout; }, /** * Set send data * @method setSendData */ setSendData: function (data) { this.sendData = $.extend(this.sendData, data || {}); }, /** * Get send data * @method getSendData */ getSendData: function () { return this.sendData; }, /** * Get loaded data * @method initialize */ getData: function () { return this.data; }, /** * Filter loaded data * @method processFilterData * @param {Object} data */ processFilterData: function (data) { if (data !== null && typeof data !== "undefined") { if (data.hasOwnProperty('status') === true && data.hasOwnProperty('data') === true && data.status === 0 && data !== null) { return data.data; } else if (data.hasOwnProperty('id') === true) { return data; } else { if (this.logger !== null) { this.logger.warn(this.Class.fullName, "Error while filtering Data."); this.logger.warn(data); } } } return null; }, /** * Load data * @method load * @param {Object} url */ load: function (url) { var self = this; $.ajax({ type: this.requestType, url: url, timeout: this.timeout, data: this.sendData, dataType: this.dataType, success: function (data, textStatus) { self.onSuccess(data, textStatus); }, error: function (data, textStatus) { self.onError(textStatus); } }); }, /** * On success * @method onSuccess * @param {Object} data * @param {String} textStatus */ onSuccess: function (data, textStatus) { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "onSuccess status: " + textStatus); } this.data = this.processFilterData(data); if (typeof this.completeHandler === 'function') { this.completeHandler(this.handlerData, textStatus); } }, /** * onError * @method onError * @param {Object} textStatus */ onError: function (textStatus) { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "onError status :" + textStatus); } this.data = null; if (typeof this.completeHandler === 'function') { this.completeHandler(this.handlerData, textStatus); } } }); ================================================ FILE: src/player/local-storage-manager.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Class en charge de gérer le stockage des données local * @class localStorageManager * @namespace fr.ina.amalia.player.parsers * @module player * @constructor */ $.Class("fr.ina.amalia.player.LocalStorageManager", { storageNamespace: 'ina.media.player' }, { /** * Defines configuration * @property settings * @type {Object} * @default {} */ settings: {}, /** * In charge to render messages in the web console output * @property logger * @type {Object} * @default null */ logger: null, /** * Local storage data * @property data * @type {Object} * @default null */ data: null, /** * Init this class * @constructor * @method init */ init: function () { this.initializeStorage(); }, /** * Initialize local storage data * @method initialize */ initializeStorage: function () { if (typeof localStorage !== 'undefined') { try { if (localStorage.hasOwnProperty(this.Class.storageNamespace) === false) { localStorage.setItem(this.Class.storageNamespace, JSON.stringify({})); } this.data = JSON.parse(localStorage.getItem(this.Class.storageNamespace)); } catch (e) { this.data = null; } } else { this.data = null; } }, /** * Update local storage data * @method initialize */ updateDataStorage: function () { try { if (typeof localStorage !== 'undefined') { localStorage.setItem(this.Class.storageNamespace, JSON.stringify(this.data)); } } catch (e) { this.data = null; } }, /** * Method check if has key * @method hasItem * @param {String} key */ hasItem: function (key) { return (this.data !== null && this.data.hasOwnProperty(key) === true); }, /** * Return key data * @method getItem * @param {String} key */ getItem: function (key) { if (this.data !== null && this.data.hasOwnProperty(key) === true) { return this.data[key]; } return null; }, /** * Set item with key and value * @method setItem * @param {String} key * @param {String} value */ setItem: function (key, value) { try { if (this.data !== null && typeof key !== 'undefined' && typeof value !== 'undefined') { this.data[key] = value; this.updateDataStorage(); } } catch (e) { return null; } return true; }, /** * Remove item with key * @method removeItem * @param {String} key */ removeItem: function (key) { if (this.data !== null && typeof key !== 'undefined') { this.data.splice(key, 1); this.updateDataStorage(); } }, /** * Clear all data * @method clear */ clear: function () { if (typeof localStorage !== 'undefined') { localStorage.removeItem(this.Class.storageNamespace); } } }); ================================================ FILE: src/player/media-factory.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Media factory * @class MediaFactory * @namespace fr.ina.amalia.player * @module player * @param {Object} mediaContainer * @param {Object} settings * @constructor */ $.Class("fr.ina.amalia.player.MediaFactory", {}, { /** * Defines configuration * @property settings * @type {Object} * @default {} */ settings: {}, /** * In charge to render messages in the web console output * @property logger * @type {Object} * @default null */ logger: null, /** * Player dom element * @property mediaContainer * @type {Object} * @default null */ mediaContainer: null, /** * Player instance * @property player * @type {Object} * @default null */ player: null, /** * Error message container * @property errorContainer * @type {Object} * @default null */ errorContainer: null, /** * Last Seek time * @property lastSeekTime * @type {Object} * @default null */ lastSeekTime: null, /** * Init this class * @constructor * @method init * @param {Object} mediaContainer * @param {Object} settings */ init: function (mediaContainer, settings) { this.mediaContainer = $(mediaContainer); this.lastSeekTime = 0; this.settings = $.extend({ player: 'default', src: null, poster: "", autoplay: false, plugins: {}, callbacks: {}, duration: null, debug: false }, settings || {}); if (fr.ina.amalia.player.log !== undefined && fr.ina.amalia.player.log.LogHandler !== undefined) { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } this.initialize(); }, /** * Initialize * @method initialize * @throws {Object} */ initialize: function () { try { if (this.settings.src !== null) { this.loadPlayer(); if (this.logger !== null) { this.logger.trace(this.Class.fullName, "initialize"); } } else { this.createErrorContainer(); this.setErrorCode(fr.ina.amalia.player.PlayerErrorCode.MEDIA_FILE_NOT_FOUND); } } catch (error) { this.createErrorContainer(); this.setErrorCode(fr.ina.amalia.player.PlayerErrorCode.ERROR_HTML5_SUPPORT); if (this.logger !== null) { this.logger.error(error.stack); } } }, /** * Method for create error container elements. * @method createErrorContainer */ createErrorContainer: function () { this.errorContainer = $('

', { 'class': 'ajs-error' }); this.errorContainer.hide(); this.mediaContainer.append(this.errorContainer); }, /** * Set error code * @method setErrorCode * @param {Object} errorCode */ setErrorCode: function (errorCode) { if (typeof this.errorContainer !== "undefined") { var messageContainer = $('

', { text: fr.ina.amalia.player.PlayerErrorCode.getMessage(errorCode) }); this.errorContainer.html(messageContainer); this.errorContainer.show(); } }, /** * Load player * @method loadPlayer */ loadPlayer: function () { if (this.settings.player === "default") { this.loadHtml5MediaPlayer(); } else { /* jslint evil: true */ this.player = eval("new " + this.settings.player + "(this.settings, this.mediaContainer);"); } }, /** * Load player html5 * @method loadHtml5MediaPlayer */ loadHtml5MediaPlayer: function () { if (this.logger !== null) { this.logger.info("Load html 5 media player"); } var browserFeatureDetection = new fr.ina.amalia.player.helpers.BrowserFeatureDetection(); if (browserFeatureDetection.isSupportsVideos()) { this.player = new fr.ina.amalia.player.PlayerHtml5(this.settings, this.mediaContainer); } else { if (this.logger !== null) { this.logger.error("Your browser does not support the video tag."); } throw new Error("Your browser does not support the video tag."); } }, /** * Return player instance * @method getPlayer * @returns {Object} */ getPlayer: function () { return this.player; } }); ================================================ FILE: src/player/media-type-dash-mpeg.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Desh-mpeg streaming * @class DashMpeg * @namespace fr.ina.amalia.player.media.type * @module player * @constructor * @param {Object} settings * @param {Object} mediaPlayer player instance */ fr.ina.amalia.player.mediaTypeManager.extend("fr.ina.amalia.player.media.type.DashMpeg", {}, { /** * Dash context * @property context * @type {Object} * @default null */ context: null, /** * Dash player instance * @property context * @type {Object} * @default null */ dashPlayer: null, /** * Initialize dash context * @method initialize */ initialize: function () { this.context = new Dash.di.DashContext(); this.dashPlayer = new MediaPlayer(this.context); }, /** * Set media source file (mdp file) * @param {String} url * @method setSrc */ setSrc: function (url) { this.dashPlayer.setAutoPlay(this.settings.autoplay); this.dashPlayer.startup(); this.dashPlayer.attachView(this.mediaPlayer.get(0)); // Fetches and parses the manifest - WARNING the callback is non-standard "error-last" style this.dashPlayer.retrieveManifest(url, $.proxy(this.initializeDashJS, this)); this.dashPlayer.videoElementExt = this.mediaPlayer.get(0); if (this.logger !== null) { this.logger.trace(this.Class.fullName, "set dash src :" + this.url); } }, initializeDashJS: function (manifest, err) { if (typeof err === "object") { this.mainObj.setErrorCode(fr.ina.amalia.player.PlayerErrorCode.ERROR_MANIFEST_DASH); } else { // Attach the source with any protection data this.dashPlayer.attachSource(manifest); } } }); ================================================ FILE: src/player/media-type-manager.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * Base class for media type file * @class mediaTypeManager * @namespace fr.ina.amalia.player.media.type * @module player * @constructor * @param {Object} settings * @param {Object} mediaPlayer player instance */ $.Class("fr.ina.amalia.player.mediaTypeManager", {}, { /** * Instance of Player HTML5 * @property mediaPlayer * @type {Object} HTMLVideoElement * @default null */ mediaPlayer: null, /** * Instance of main class * @property mainObj * @type {Object} HTMLVideoElement * @default null */ mainObj: null, /** * logger instance * @property logger * @type {Object} HTMLVideoElement * @default null */ logger: null, /** * Configuration * @property settings * @type {Object} * @default "{}" */ settings: {}, init: function (settings, mainObj) { this.mediaPlayer = mainObj.mediaPlayer; this.mainObj=mainObj; this.namespace = this.Class.fullName; this.settings = $.extend({ debug: false, internalPlugin: false }, settings || {}); if (fr.ina.amalia.player.log !== undefined && fr.ina.amalia.player.log.LogHandler !== undefined) { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } if (this.mediaPlayer === null) { throw new Error("Can't initialize plugin name" + this.Class.fullName); } this.initialize(); }, /** * initialize * @method initialize */ initialize: function () { } }); ================================================ FILE: src/player/metadata/localisation-manager.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * For manage localisation block * @class LocalisationManager * @namespace fr.ina.amalia.player * @module player * @constructor * @param {Object} settings * @param {Object} mediaPlayer player instance */ $.Class("fr.ina.amalia.player.LocalisationManager", {}, { /** * Logger instance * @property logger * @type {Object} HTMLVideoElement * @default null */ logger: null, /** * Instance of Player HTML5 * @property mediaPlayer * @type {Object} HTMLVideoElement * @default null */ localisation: null, /** * Init this class * @constructor * @method init * @param {Object} settings */ init: function () { this.localisation = []; }, /** * in charge to set localisation * @param {type} localisation */ setLoc: function (localisation) { this.localisation = localisation; }, /** * Return localisation tcin tcout * @returns return timecode */ getLocTc: function () { if (this.localisation !== null && this.localisation.length > 1) { //sort by tc this.localisation.sort(function (obj1, obj2) { obj1.tc = (typeof obj1.tc === "number") ? obj1.tc : parseFloat(fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(obj1.tc)); obj2.tc = (typeof obj2.tc === "number") ? obj2.tc : parseFloat(fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(obj2.tc)); delete obj1.firstItem; delete obj1.lastItem; delete obj1.tcRange; return obj1.tc - obj2.tc; }); var _firstItem = this.localisation[0]; var _lastItem = this.localisation[this.localisation.length - 1]; //add range for (var i = 0; i < this.localisation.length; i++) { var item = this.localisation[i]; item.tcRange = { min: _firstItem.tc, max: _lastItem.tc }; item.subItem = true; } if (_firstItem.hasOwnProperty('tc') && _lastItem.hasOwnProperty('tc')) { _firstItem.firstItem = true; _lastItem.lastItem = true; delete _firstItem.range; delete _lastItem.range; _firstItem.tcRange = { max: _lastItem.tc }; _lastItem.tcRange = { min: _firstItem.tc }; return { tcin: _firstItem.tc, tcout: _lastItem.tc }; } } return null; }, /** * In charge to updata localisation block for spatial data * @method updateSpacialLocBlock * @param {Object} localisations */ updateSpacialLocBlock: function (localisations) { if (localisations !== null && localisations.length > 0) { for (var i = 0; i < localisations.length; i++) { var loc = localisations[i]; if (loc.hasOwnProperty('sublocalisations') && typeof loc.sublocalisations === "object" && loc.sublocalisations !== null) { if (loc.sublocalisations.localisation.length > 0) { loc.sublocalisations.localisation.sort(function (obj1, obj2) { return obj1.tc - obj2.tc; }); for (var j = 0; j < loc.sublocalisations.localisation.length; j++) { var item = loc.sublocalisations.localisation[j]; if (item.tc === null && item.deleted === true) { loc.sublocalisations.localisation.splice(j, 1); } } loc.sublocalisations.localisation.sort(function (obj1, obj2) { return obj1.tc - obj2.tc; }); if (loc.sublocalisations.localisation.length === 1) { var _tmpItem = loc.sublocalisations.localisation[0]; loc.tc = parseFloat(_tmpItem.tc); loc.shape = $.extend({}, _tmpItem.shape); loc.sublocalisations = null; delete (loc.tcin); delete (loc.tcout); return true; } else if (loc.sublocalisations.localisation.length > 1) { var _firstItem = loc.sublocalisations.localisation[0]; var _lastItem = loc.sublocalisations.localisation[loc.sublocalisations.localisation.length - 1]; if (_firstItem.hasOwnProperty('tc') && _lastItem.hasOwnProperty('tc')) { loc.tc = parseFloat(_firstItem.tc); loc.tcin = parseFloat(_firstItem.tc); loc.tcout = parseFloat(_lastItem.tc); return true; } } } } else if (loc.hasOwnProperty('delete') && loc.delete === true) { localisations.splice(i, 1); } } } return false; }, /** * In charge to updata localisation block for spatial data * @method updateLocBlock * @param {Object} localisations */ updateLocBlock: function (localisations) { if (localisations !== null && localisations.length > 0) { for (var i = localisations.length - 1; i >= 0; i--) { var loc = localisations[i]; if (loc.tc === null && loc.tcin === null) { localisations.splice(i, 1); } else if (loc.hasOwnProperty('sublocalisations') && loc.sublocalisations !== null && typeof loc.sublocalisations === "object" && loc.sublocalisations.localisation.length > 0) { for (var j = loc.sublocalisations.localisation.length - 1; j >= 0; j--) { var item = loc.sublocalisations.localisation[j]; if (item.tc === null && item.hasOwnProperty('deleted') && item.deleted === true) { loc.sublocalisations.localisation.splice(j, 1); } } } } } return false; }, /** * In charge to shift localisation block with spatial data * @method shiftSpacialLocBlock * @param {Object} localisations */ shiftSpacialLocBlock: function (loc, tcin) { var shiftTc = tcin - loc.tcin; loc.tcout += shiftTc; if (loc.hasOwnProperty('sublocalisations') && typeof loc.sublocalisations === "object") { if (loc.sublocalisations.localisation.length > 0) { loc.sublocalisations.localisation.sort(function (obj1, obj2) { return obj1.tc - obj2.tc; }); for (var j = 0; j < loc.sublocalisations.localisation.length; j++) { var item = loc.sublocalisations.localisation[j]; item.tc += shiftTc; } } return true; } return false; }, /** * In charge to shift localisation with tc * @method shiftLocBlock * @param {Object} localisations */ shiftLocBlock: function (metadata, shiftTc, tcin, tcout, selected) { if (typeof metadata === "object" && metadata.length > 0) { metadata.sort(function (obj1, obj2) { return obj1.tc - obj2.tc; }); for (var j = 0; j < metadata.length; j++) { var item = metadata[j]; if ((selected === false) || (selected === true && item.hasOwnProperty('selected') && item.selected === true)) { if (item.hasOwnProperty('tc') && item.tc !== null) { //item.tc = Math.min(Math.max(tcin, item.tc + shiftTc), tcout); item.tc += shiftTc; } if (item.hasOwnProperty('tcin') && item.tcin !== null) { item.tcin += shiftTc; } if (item.hasOwnProperty('tcout') && item.tcout !== null) { item.tcout += shiftTc; } } } return true; } return false; } }); ================================================ FILE: src/player/metadata/metadata-manager.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * In charge to manage all metadata * @class MetadataManager * @namespace fr.ina.amalia.player * @module player * @constructor * @param {Object} settings * @param {Object} mediaPlayer player instance */ $.Class("fr.ina.amalia.player.MetadataManager", {}, { /** * Instance of Player HTML5 * @property mediaPlayer * @type {Object} HTMLVideoElement * @default null */ mediaPlayer: null, /** * Logger instance * @property logger * @type {Object} HTMLVideoElement * @default null */ logger: null, /** * Configuration * @property settings * @type {Object} * @default "{}" */ settings: {}, /** * Contains list of blocks metadata * @property listOfBlocks * @type {Object} * @default "[]" */ listOfBlocks: {}, /** * List of metadata with id * @property listOfMetadata * @type {Object} * @default null */ listOfMetadata: [], /** * Contains list of selected items * @property listOfSelectedItems * @type {Object} * @default "[]" */ listOfSelectedItems: [], /** * Selected metadata id * @property selectedMetadataId * @type {Number} * @default 0 */ selectedMetadataId: null, /** * Init * @method initialize */ init: function (settings, mediaPlayer) { this.mediaPlayer = mediaPlayer; this.listOfBlocks = {}; this.listOfMetadata = []; this.listOfSelectedItems = []; this.selectedMetadataId = null; this.selectedMetadataId = null; // Settings this.settings = $.extend({ debug: false, internalPlugin: false }, settings || {}); // Logger if (fr.ina.amalia.player.log !== undefined && fr.ina.amalia.player.log.LogHandler !== undefined) { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } if (this.mediaPlayer === null) { throw new Error("Can't initialize plugin name" + this.Class.fullName); } }, /** * Return the block of metadata * @method getBlocksMetadata * @return Array return the list of blocks with data */ getBlocksMetadata: function () { try { var data = {}; for (var key in this.listOfBlocks) { if (this.listOfBlocks.hasOwnProperty(key)) { var d = JSON.parse(JSON.stringify(this.listOfBlocks[key])); if (typeof this.listOfMetadata[key] !== 'undefined') { d.localisation = JSON.parse(JSON.stringify(this.listOfMetadata[key], function (key, value) { if (key === "refLoc") { return undefined; } else { return value; } })); } else { d.localisation = null; } data[key] = d; } } return data; } catch (error) { if (this.logger !== null) { this.logger.warn("Error to return blocks"); this.logger.error(error.stack); } } return null; }, /** * Return the block of metadata * @method getBlockMetadata * @return Array return block without data */ getBlockMetadata: function (id) { var data = null; try { if (typeof this.listOfBlocks[id] !== 'undefined') { data = this.listOfBlocks[id]; if (typeof this.listOfMetadata[id] !== 'undefined') { data.localisation = JSON.parse(JSON.stringify(this.listOfMetadata[id], function (key, value) { return (key === "refLoc") ? undefined : value; })); } else { data.localisation = null; } } } catch (error) { if (this.logger !== null) { this.logger.warn("Error to return blocks"); this.logger.error(error.stack); } } return data; }, /** * In charge to update the block metadata with * @method updateBlockMetadata * @param id id of metadata * @param data block data * @param action trigger action */ updateBlockMetadata: function (id, data, action) { try { if (typeof data === "object") { this.listOfBlocks[id] = $.extend(this.listOfBlocks[id], JSON.parse(JSON.stringify(data))); } else if (typeof data === "string") { this.listOfBlocks[id] = $.extend(this.listOfBlocks[id], JSON.parse(data)); } if (typeof this.listOfMetadata[id] === 'undefined') { this.listOfMetadata[id] = []; } if (this.listOfBlocks[id].hasOwnProperty('localisation') && this.listOfBlocks[id].localisation) { this.listOfMetadata[id] = this.listOfBlocks[id].localisation; } this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: id, action: action }); } catch (error) { if (this.logger !== null) { this.logger.warn("Error to add blocks"); this.logger.error(error.stack); } } }, /** * Remove the block metadata with id metadata * @method removeBlockMetadata * @param {String} id */ removeBlockMetadata: function (id) { return delete (this.listOfBlocks[id]); }, /** * In charge to add metadata, it is called by metadata parser * @method addAllMetadata * @param {Object} parsedData * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ addAllMetadata: function (parsedData) { if (typeof parsedData === "object" && parsedData !== null) { if (typeof parsedData.length !== "undefined") { for (var d in parsedData) { if (parsedData[d].hasOwnProperty('id')) { if (typeof this.listOfMetadata[parsedData[d].id] === 'undefined') { this.listOfMetadata[parsedData[d].id] = []; } for (var j = 0; j < parsedData[d].list.length; j++) { var obj = parsedData[d].list[j]; this.listOfMetadata[parsedData[d].id].push(obj); } if (parsedData[d].hasOwnProperty('type') === true) { var _data = parsedData[d]; this.updateBlockMetadata(_data.id, { type: _data.type, id: _data.id, viewControl: _data.hasOwnProperty('viewControl') ? _data.viewControl : null, label: _data.hasOwnProperty('label') ? _data.label : _data.id }); } else { this.updateBlockMetadata(parsedData[d].id, {}); } this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: parsedData[d].id }); if (this.logger !== null) { this.logger.info("AddAllMetadata ID:" + parsedData[d].id); } } else { if (this.logger !== null) { this.logger.warn("parseData : Error to find data type."); } } } } else { if (typeof this.listOfMetadata[parsedData.id] === 'undefined') { this.listOfMetadata[parsedData.id] = []; } for (var k = 0; k < parsedData.list.length; k++) { var o = parsedData.list[k]; this.listOfMetadata[parsedData.id].push(o); } this.updateBlockMetadata(parsedData.id, { id: parsedData.id, label: parsedData.hasOwnProperty('label') ? parsedData.label : parsedData.id, type: parsedData.hasOwnProperty('type') ? parsedData.type : '', viewControl: parsedData.hasOwnProperty('viewControl') ? parsedData.viewControl : null }); this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: parsedData.id }); if (this.logger !== null) { this.logger.info("Add Metadata ID:" + parsedData.id); } } } else { if (this.logger !== null) { this.logger.warn("Error to add metadata."); this.logger.warn(parsedData); } } }, /** * In charge to return metadata by id * @method addMetadataById * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ addMetadataById: function (id, parsedData) { if (typeof this.listOfMetadata[id] === 'undefined') { this.listOfMetadata[id] = []; this.updateBlockMetadata(id, {}); } if (typeof parsedData === "object") { for (var j = 0; j < parsedData.length; j++) { var obj = parsedData[j]; this.listOfMetadata[id].push(obj); } this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: id }); } }, /** * In charge to replace metadata by id * @method replaceAllMetadataById * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ replaceAllMetadataById: function (id, parsedData) { this.listOfMetadata[id] = []; if (typeof parsedData === "object") { this.listOfMetadata[id] = []; for (var j = 0; j < parsedData.length; j++) { var obj = parsedData[j]; this.listOfMetadata[id].push(obj); } this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: id }); } }, /** * In charge to delete metadata by id * @method deleteAllMetadataById * @param {Object} data * @event fr.ina.amalia.player.PlayerEventType.DATA_CHANGE */ deleteAllMetadataById: function (id) { if (typeof this.listOfMetadata[id] !== "undefined") { var deleted = false; if (this.listOfMetadata.hasOwnProperty(id)) { /* jslint evil: true */ deleted = eval("delete this.listOfMetadata['" + id + "']"); } if (deleted) { this.removeBlockMetadata(id); this.selectedMetadataId = null; this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.SELECTED_METADATA_CHANGE, { metadataId: this.selectedMetadataId }); this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: id, action: 'deleteBlock' }); } } return false; }, /** * In charge to add metadata item and return reference of the pushed element * @method addMetadataItem */ addMetadataItem: function (metadataId, data) { if (typeof this.listOfMetadata[metadataId] !== 'object') { this.listOfMetadata[metadataId] = []; } if (typeof data === "object") { var len = this.listOfMetadata[metadataId].push(data); var refData = this.listOfMetadata[metadataId][len - 1]; this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: metadataId }); return refData; } }, /** * Return metadata by id * @method getMetadataById * @param {String} id * @return {Array} */ getMetadataById: function (id) { return (typeof this.listOfMetadata[id] === 'undefined') ? null : this.listOfMetadata[id]; }, /** * Set metadata by id * @method setMetadataById * @param {String} id * @param {Object} data * @return {Array} */ setMetadataById: function (id, data) { if (typeof data === "object") { this.listOfMetadata[id] = data; } else if (typeof data === "string") { try { var jsonData = JSON.parse(data); this.listOfMetadata[id] = jsonData; } catch (e) { return false; } } else { return false; } this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: id }); return true; }, /** * In charge to remove metadata * @method removeMetadataById */ removeMetadataById: function (id) { this.listOfMetadata[id] = []; this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: id }); }, /** * Return a metadata by specified time code. * @method getMetadataWithRange * @param id * @param tcin * @param tcout * @return {Array} */ getMetadataWithRange: function (id, tcin, tcout) { var metadatas = this.getMetadataById(id); var results = []; if (metadatas !== null && typeof metadatas === "object") { results = $.grep(metadatas, function (n) { return (n.hasOwnProperty('tc') && n.tc !== null) ? (n.tc >= tcin && n.tc <= tcout) : true; }); if (this.logger !== null) { this.logger.trace(this.Class.fullName, "getMetadataWithRange Id:" + id + " Tcin:" + tcin + " Tcout:" + tcout + " Number of Elements:" + metadatas.length); } } else { if (this.logger !== null) { this.logger.warn("GetMetadataWithRange: No data id:" + id); } } return results; }, /** selected metadata* */ /** * Return selected component id * @method getSelectedMetadataId */ getSelectedMetadataId: function () { return (this.selectedMetadataId !== null) ? this.selectedMetadataId.toString() : null; }, /** * Set selected component id * @method setSelectedMetadataId */ setSelectedMetadataId: function (metadataId) { if (this.selectedMetadataId !== metadataId) { this.removeAllSelectedItems(); this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.DATA_CHANGE, { id: this.selectedMetadataId }); this.selectedMetadataId = metadataId; this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.SELECTED_METADATA_CHANGE, { metadataId: this.selectedMetadataId }); } }, /** selected items* */ /** * Return selected items * @method getSelectedItems * @return {Array} */ getSelectedItems: function () { return this.listOfSelectedItems; }, /** * In charge to selected item * @method addSelectedItem * @param item */ addSelectedItem: function (item) { if (item !== null && typeof item === "object") { item.selected = true; } this.listOfSelectedItems.push(item); this.mediaPlayer.getContainer().trigger(fr.ina.amalia.player.PlayerEventType.SELECTED_ITEMS_CHANGE, {item: item}); }, /** * In charge to clear selected iteme * @method removeSelectedItem * @param idx */ removeSelectedItem: function (idx) { if (this.listOfSelectedItems[idx] !== 'undefined' && isNaN(idx) === false) { var data = this.listOfSelectedItems[idx]; if (data !== null && typeof data === "object" && data.hasOwnProperty('selected') === true) { data.selected = false; } if (idx > -1) { this.listOfSelectedItems.splice(idx, 1); } } }, /** * In charge to remove all selected items * @method removeAllSelectedItems */ removeAllSelectedItems: function () { if (typeof this.listOfSelectedItems !== 'undefined' && this.listOfSelectedItems.hasOwnProperty('length') && this.listOfSelectedItems.length > 0) { for (var i = 0; i < this.listOfSelectedItems.length; i++) { var data = this.listOfSelectedItems[i]; if (data !== null && typeof data === "object" && data.hasOwnProperty('selected') === true) { data.selected = false; } } } this.listOfSelectedItems = []; } }); ================================================ FILE: src/player/parsers/base-parser-metadata.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * In charge to parse metadata (json) * @class MetadataParser * @namespace fr.ina.amalia.player.parsers * @module player * @constructor * @param {Object} settings Defines the configuration of this class */ $.Class("fr.ina.amalia.player.parsers.BaseParserMetadata", {}, { /** * Defines configuration * @property settings * @type {Object} * @default {} */ settings: {}, /** * In charge to render messages in the web console output * @property logger * @type {Object} * @default null */ logger: null, /** * Parsed data * @property data * @type {Object} * @default null */ data: null, /** * Init this class * @constructor * @method init * @param {Object} settings */ init: function (settings) { this.settings = $.extend({ debug: false, mainLevel: false }, settings || {}); if (typeof fr.ina.amalia.player.log !== "undefined" && typeof fr.ina.amalia.player.log.LogHandler !== "undefined") { this.logger = new fr.ina.amalia.player.log.LogHandler({ enabled: this.settings.debug }); } }, /** * Filter loaded data * @method processFilterData * @param {Object} data */ processParserData: function (data) { if (data !== null && typeof data !== "undefined") { if (data.hasOwnProperty('status') === true && data.hasOwnProperty('data') === true && data.status === 0 && data !== null) { return this.parseData(data.data); } else if (data.hasOwnProperty('id') === true) { return this.parseData(data); } else if (data.length !== "undefined") { return this.parseData(data); } } if (this.logger !== null) { this.logger.warn(this.Class.fullName, "Error while filtering Data."); this.logger.warn(data); } return null; }, /** * Parse data * @method parseData * @param {Object} data * @returns {metadataParserAnonym$1.parseData@call;getData|Array} */ parseData: function (data) { var parsedMetadata = null; if (this.logger !== null) { this.logger.trace(this.Class.fullName, "parseData"); } // if data has many entity if (typeof data.length !== "undefined") { parsedMetadata = []; for (var d in data) { if (typeof data[d] === "string") { try { data[d] = JSON.parse(data[d]); parsedMetadata.push(this.getData(data[d])); } catch (e) { if (this.logger !== null) { this.logger.warn("parseData : Error to find data type."); } } } else if (data[d].hasOwnProperty('id') === true) { parsedMetadata.push(this.getData(data[d])); } else { if (this.logger !== null) { this.logger.warn("parseData : Error to find data type."); } } } } else if (data.hasOwnProperty('id') === true) { parsedMetadata = this.getData(data); } else { if (this.logger !== null) { this.logger.warn("parseData : Error to find data type."); } } return parsedMetadata; }, /** * Return parsed localisations data * @method methodName * @param {Object} data * @returns {Array} */ getData: function (data) { var parsedMetadata = null; parsedMetadata = {}; parsedMetadata.id = data.id; parsedMetadata.type = data.type; parsedMetadata.viewControl = data.hasOwnProperty('viewControl') ? data.viewControl : null; parsedMetadata.label = data.hasOwnProperty('label') ? data.label : data.id; parsedMetadata.list = []; if (data.hasOwnProperty('localisation') === true && data.localisation !== null && data.localisation.length > 0) { var localisations = null; if (this.settings.hasOwnProperty('parameters') && this.settings.parameters !== null && this.settings.parameters.hasOwnProperty('mainLevel') && this.settings.parameters.mainLevel === true) { localisations = data.localisation; } else { localisations = (data.localisation[0].hasOwnProperty('sublocalisations') === true && data.localisation[0].sublocalisations !== null && data.localisation[0].sublocalisations.hasOwnProperty('localisation')) ? data.localisation[0].sublocalisations.localisation : data.localisation; } var entry = null; var localisation = null; var label = ''; var thumb = ''; if (localisations !== null && typeof localisations !== "undefined" && localisations.hasOwnProperty('length')) { for (var i = 0; i < localisations.length; i++) { localisation = localisations[i]; label = localisation.hasOwnProperty('label') ? localisation.label : ''; thumb = localisation.hasOwnProperty('thumb') ? localisation.thumb : null; if (localisation.hasOwnProperty('tcin') === true && localisation.hasOwnProperty('tcout') === true) { entry = { id: (localisation.hasOwnProperty('id') === true) ? localisation.id : null, shape: (localisation.hasOwnProperty('shape') === true) ? localisation.shape : null, data: (localisation.hasOwnProperty('data') === true) ? localisation.data : null, sublocalisations: (localisation.hasOwnProperty('sublocalisations') === true) ? localisation.sublocalisations : null, label: label, thumb: thumb, tclevel: (localisation.hasOwnProperty('tclevel') === true) ? localisation.tclevel : 0, tc: (typeof localisation.tc === "number") ? localisation.tc : fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(localisation.tc), tcin: (typeof localisation.tcin === "number") ? localisation.tcin : fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(localisation.tcin), tcout: (typeof localisation.tcout === "number") ? localisation.tcout : fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(localisation.tcout), duration: fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(localisation.tcout) - fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(localisation.tcin), type: (localisation.hasOwnProperty('type') === true) ? localisation.type : null, score: (localisation.hasOwnProperty('score') === true) ? parseFloat(localisation.score) : null }; parsedMetadata.list.push(entry); } else if (localisation.hasOwnProperty('tc') === true && localisation.tc !== null) { entry = { id: (localisation.hasOwnProperty('id') === true) ? localisation.id : null, shape: (localisation.hasOwnProperty('shape') === true) ? localisation.shape : null, data: (localisation.hasOwnProperty('data') === true) ? localisation.data : null, sublocalisations: (localisation.hasOwnProperty('sublocalisations') === true) ? localisation.sublocalisations : null, label: label, thumb: thumb, tclevel: (localisation.hasOwnProperty('tclevel') === true) ? localisation.tclevel : 0, tc: (typeof localisation.tc === "number") ? localisation.tc : fr.ina.amalia.player.helpers.UtilitiesHelper.convertHourToSeconde(localisation.tc), type: (localisation.hasOwnProperty('type') === true) ? localisation.type : null, score: (localisation.hasOwnProperty('score') === true) ? parseFloat(localisation.score) : null }; parsedMetadata.list.push(entry); } } } } return parsedMetadata; } }); ================================================ FILE: src/player/player-html5.js ================================================ /** * Copyright (c) 2015-2023 Institut National de l'Audiovisuel, INA * * This file is part of amalia.js * * Amalia.js is free software: you can redistribute it and/or modify it under * the terms of the MIT License * * Redistributions of source code, javascript and css minified versions must * retain the above copyright notice, this list of conditions and the following * disclaimer * * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission * * You should have received a copy of the MIT License along with * amalia.js. If not, see * * Amalia.js is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ /** * In charge of the player html5 * @class PlayerHtml5 * @module player * @namespace fr.ina.amalia.player * @constructor * @param {Object} settings * @param {Object} mediaContainer */ fr.ina.amalia.player.BasePlayer.extend("fr.ina.amalia.player.PlayerHtml5", {}, { /** * Method in charge to initialize player : - Create containers - Load * plugins * @method initialize * @override */ initialize: function () { this.lastSeekTime = 0; this.createPlayer(); this.setSrc(this.settings.src, this.settings.autoplay); // set default volume this.setVolume((this.localStorageManager.hasItem('volume') === false) ? this.settings.defaultVolume : this.localStorageManager.getItem('volume')); this._super(); }, /** * In charge to set source with autoplay state * @param {String} src * @param {Boolean} autoplay * @method setSrc */ setSrc: function (src, autoplay) { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "setSrc:" + src); } if (this.settings.mediaType === "mpd") { this.mediaTypeManager = new fr.ina.amalia.player.media.type.DashMpeg(this.settings, this); this.mediaTypeManager.setSrc(src); } else { // charge la video this.mediaPlayer.find('source:first').attr({ src: src }); if (this.settings.mediaType !== "") { this.mediaPlayer.find('source:first').attr('type', this.settings.mediaType); } this.load(); } this._super(src, autoplay); }, /** * In charge to create Player dom element * @method createPlayer */ createPlayer: function () { if (this.logger !== null) { this.logger.trace(this.Class.fullName, "createPlayer"); } this.mediaPlayer = $('