From a59698176538ae0d3f84fd6a3e9b159278b547e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=BD=D0=B0=D0=B5=D0=B2?= Date: Tue, 5 Aug 2025 12:34:55 +0000 Subject: [PATCH] =?UTF-8?q?#65991=20=D0=A2=D0=BE=D1=80=D0=BC=D0=BE=D0=B7?= =?UTF-8?q?=D0=B0=20=D0=B8=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=BD?= =?UTF-8?q?=D0=B0=20WebOS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Caddyfile | 9 + Toolset/Tizen/BasicUI/.sign/.manifest.tmp | 8 +- .../Tizen/BasicUI/.sign/author-signature.xml | 71 +++---- Toolset/Tizen/BasicUI/.sign/signature1.xml | 76 +++----- Toolset/Tizen/BasicUI/config.xml | 11 +- Toolset/Tizen/BasicUI/index.html | 40 ++-- Toolset/Tizen/BasicUI/index_min_test.html | 73 +++++++ Toolset/Tizen/DUIDs.txt | 1 + Toolset/WebOS/HostedWebApp-main/index.html | 6 +- .../WebOS/HostedWebApp-main/webOSTV-dev.js | 1 + Toolset/WebOS/HostedWebApp-main/webOSTV.js | 1 + demo/dash_playready_vod.html | 181 +++++++++++++++++ demo/dash_widevine_vod.html | 182 ++++++++++++++++++ demo/index.html | 6 +- demo/index_dash_widevine_live_voka.html | 1 - demo/index_hls_fairplay_vod.html | 3 +- demo/index_hls_widevine_vod.html | 1 - demo/index_web.html | 182 ++++++++++++++++++ .../channels/dash-playready-vod/stream.json | 21 ++ .../dash-widevine-live-voka/stream.json | 2 +- .../v1/channels/dash-widevine-vod/stream.json | 22 +++ .../stream.json | 22 ++- docker-compose.caddy.yml | 45 +++++ src/assets/scss/components/_poster.scss | 1 + src/internal/drm/dash/VokaDash.ts | 34 ++-- src/internal/player/VokaCorePlayer.ts | 151 +++++++++------ .../player/native/VokaSourceHandler.ts | 5 +- .../player/native/tizen/tech/AVPlayHelper.ts | 101 +++++++--- .../player/native/tizen/tech/VokaTizenTech.ts | 72 ++++--- .../sourcehandler/VokaWebOSSourceHandler.ts | 5 +- .../player/native/webos/tech/VokaWebOSTech.ts | 14 +- src/plugins/VokaMagicRemotePlugin.ts | 15 +- src/public/VokaPlayerImpl.ts | 5 +- 33 files changed, 1096 insertions(+), 272 deletions(-) create mode 100644 Caddyfile create mode 100755 Toolset/Tizen/BasicUI/index_min_test.html create mode 100644 Toolset/Tizen/DUIDs.txt create mode 100644 Toolset/WebOS/HostedWebApp-main/webOSTV-dev.js create mode 100644 Toolset/WebOS/HostedWebApp-main/webOSTV.js create mode 100644 demo/dash_playready_vod.html create mode 100644 demo/dash_widevine_vod.html create mode 100644 demo/index_web.html create mode 100644 demo/v1/channels/dash-playready-vod/stream.json create mode 100644 demo/v1/channels/dash-widevine-vod/stream.json create mode 100644 docker-compose.caddy.yml diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..4afb5cf --- /dev/null +++ b/Caddyfile @@ -0,0 +1,9 @@ +{ + # email для уведомлений Let's Encrypt + email am@just-work.org +} + +# Хост и прокси +mule.jwrk.org { + reverse_proxy server:8080 +} \ No newline at end of file diff --git a/Toolset/Tizen/BasicUI/.sign/.manifest.tmp b/Toolset/Tizen/BasicUI/.sign/.manifest.tmp index 87b052b..e1cd4c1 100644 --- a/Toolset/Tizen/BasicUI/.sign/.manifest.tmp +++ b/Toolset/Tizen/BasicUI/.sign/.manifest.tmp @@ -1,7 +1,7 @@ aoc_app.zip__DEL__Xi+Vnza2bfBYCpTzhMX8HO7sSyo5JfBi17aPIXWLhlgawq3P3ec6FxooSW51jvGyPKSVHAVFXNrp NXzDtaWCXw== -config.xml__DEL__nsWBkoKSk7r0pu0ubb37gDanmRdIYcujiTiy0EErZP7ExRQajQE00K+sneKa8eSSOxH0OOecX9Ip -X++l2ykBJA== +config.xml__DEL__PRuz95KE2QodgYrVJWPvkcWMK+Y6ykfDlRjDrXdQw2vlrXdd/T/W++TTRz1pJ0LTem6M0LjxTrSS +20iJYH+sLA== css/style.css__DEL__/QJ+/nq2xebaAiLLB7s3kvL1fT/61LBickart4MZi3T2I1+AyTrBYD61Nk91tjKcvcN6RGiA5O63 5o7u57rIRQ== icon.png__DEL__BTGBG483ma/3HgWnreWF2xbdzr4F0gTRWjwxoSV+7kKBWt4UJTuv5WE4DhKdU4in2kwn/55O/qPD @@ -12,5 +12,5 @@ index.html__DEL__CYjkR+ZNwp7L/if9LsT+uFjGHChwaswBoSaFu+BgC+SlB3r0YGND4cN20rlg1At oDBqLNXYGw== js/main.js__DEL__Gfmwxx8WB6EHvN7d/Hs+7I1Blt+5u6JI6J+BljCGddvh7brF4mywWKg8iTnDvdA8Xb35l+178i0D hwV/qPVCxw== -author-signature.xml__DEL__M/eFnHFi2g/GYv0/D2hsHUZDLs9J1DZjCANuMtBFImSPGBr8F6JadxBVou43O8wyeEacadF9ZDG9 -5prLXzM+gg== +author-signature.xml__DEL__d49WGJ3MjEY0kD9IHGog/wEPNo2zS1s5pHer6i1FM2dZalIHsRuRsAVGlVxlXM5pFSCkp9kxWf5L +1J59A2Tfgw== diff --git a/Toolset/Tizen/BasicUI/.sign/author-signature.xml b/Toolset/Tizen/BasicUI/.sign/author-signature.xml index e4ac02b..cb04152 100644 --- a/Toolset/Tizen/BasicUI/.sign/author-signature.xml +++ b/Toolset/Tizen/BasicUI/.sign/author-signature.xml @@ -9,8 +9,8 @@ NXzDtaWCXw== -nsWBkoKSk7r0pu0ubb37gDanmRdIYcujiTiy0EErZP7ExRQajQE00K+sneKa8eSSOxH0OOecX9Ip -X++l2ykBJA== +PRuz95KE2QodgYrVJWPvkcWMK+Y6ykfDlRjDrXdQw2vlrXdd/T/W++TTRz1pJ0LTem6M0LjxTrSS +20iJYH+sLA== @@ -47,49 +47,42 @@ QY10fG1EWQ== -FSRsPfbPzOeJ6kYa8qwARh3fRZyttY2IZAUTNEcC+Jx6LuZxu8kZkK059HyxSfBAdPTq7r3dECv+ -Jxay4KsWTXUHSFxQLgpMkFhI4wfTiN8h6hYwHqhn9sxpUnnk8YDkUVULCgMPcjq4jUeV6K/+eDwy -BshnFQQIYiYfVPUX/tXBDevovg/x+q3j9TX/7W24Fpkq9vw/ti+nbyk7KF8Uvt6cgLA2qqoslrAr -6YOymNO40uvBoKkpcMgdoRdXgkRrQZo9vDjbhfxZua2Yc+74lTXSmXVaVYmiAFGhWGUu0AJpZB+V -nbDbicP65tQwJEAKeUTBiIm7A9SGjxX6B+5Vvw== +KF5KNSA49WfpUYrUi3vmhB3JnTjqXObPGju0bzEWw3ztUJKO/uk9JG+yRbzSW+476lnPBzMGBbRo +e+q+r39TvmCAQkhL1h/1KpZbpgjvRtY6ZWspOkFXzEVjXiRtZPhGy4IJl8DgxQqDwSToyZYkKgPZ +5HUu17mxR2xIGA9DgeM= -MIIDaTCCAlGgAwIBAgIBAjANBgkqhkiG9w0BAQ0FADCBijELMAkGA1UEBhMCS1IxFDASBgNVBAgT -C1NvdXRoIEtvcmVhMQ4wDAYDVQQHEwVTdXdvbjEmMCQGA1UEChMdU2Ftc3VuZyBFbGVjdHJvbmlj -cyBDby4sIEx0ZC4xCzAJBgNVBAsTAlZEMSAwHgYDVQQDExdTYW1zdW5nIEF1dGhvciBDQSBDbGFz -czAeFw0yNTA3MDMxNTE3MDNaFw0yNjA3MDMxNTE3MDNaMEkxCTAHBgNVBAYTADEJMAcGA1UECBMA -MQkwBwYDVQQHEwAxCTAHBgNVBAoTADEJMAcGA1UECxMAMRAwDgYDVQQDEwd0di1jZXJ0MIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjOugberkYHutm3WeIqlkcB56Juyf0D7tOOztFSWE -t0CP7i5RYzOXGDQ8ZtmCXQHYBxQB+1eNmpAwEHOkrw5R3qqBdDuBw3Hud1qJJgknrgNJHsUF1pg9 -LxkLsvRsu6cQSIoeCh9k1LU4ytquY4ZDKn+1IABxWipMp995CoqK8kOzgLQ6Mhva8BksE7vA+t+3 -KH6/d8wVSwA1vMbcnbsC+J81BrSfpHWtn38XSGPZw6D6ZKL/RHOIu6/20Ft+OXCLtu2G0M9Wg7MK -AQsB3AMRn81EF4cCEENkuw/KiNkiZCMJHXaJvbs0NKBx/tDV+PAtKcbnXGBJF4zCl/XbPIkzfwID -AQABoxowGDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIHgDANBgkqhkiG9w0BAQ0FAAOCAQEAO2yLTZ8O -Am0ad/zReLaK+b5L1438FRjYR5TVRAv/QVF7Kad1oFMDJRc9sCB6JwHyjxgTkyJInaYVojhQwazP -D7b6bj2EryUHBWCExjTFaoQ7hxZEu01E4kHtnK1OOqICgCbI3GLtH2CJXTG8QQljqKzWUIritP3o -Llp7ccuVZ2m4bWiRe8sKNfr/QJ9mAQU5BnRspcnltSTa4WhapJ/+WKc5tk7i3tl9BkMRweMA9qn/ -hOeC41f8mGweeiVLxZqxNOPcgCxEQWm50x9IFo8Dxpab0m3W1u8CyHwDteVJjjhQXg2tIgzj6S3u -ev9IuF52clygqML7oLvSKq0KC0eNUA== +MIIClTCCAX2gAwIBAgIGAZhmXwGaMA0GCSqGSIb3DQEBDQUAMFYxGjAYBgNVBAoMEVRpemVuIEFz +c29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4gRGV2 +ZWxvcGVycyBDQTAeFw0yNTA4MDExNjAyMzlaFw0yNzAxMDEwMDAwMDBaMBExDzANBgNVBAMMBmVy +dDEyMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAiwW+5wQuJiS2rNeF+b3yM5eF/GsrsJs+ +iXgXdvtvU0XVEumjQsBvwqcnskHo3Wk1GgnsJx9YRdjG4MqP1JtwoSDZE6Ly8ENplH5NvJmsoTgM +i8Fx0NW7nT2NqdpKgF8ymcgxeiHPQNgPimh4gsXakga9NJhuGh1ZsJpcZcvZuyUCAwEAAaMyMDAw +DAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcN +AQENBQADggEBAIH8WSGEJjLWGaVE64sQRwJ5JSc56yXWBJeLMyECOZ6hXPC/vA3xtswT3MBI3gj5 +65h77/0QjBaDGWzI5PKEdYwRN7XQhQl5QvaFbv1HfqqciBwB8rpBaQu4YZNvWzMBvu1Yw9jiJOmP +Dr6hDRa/pGbd7dNUt+hr0PqubhJY43eD05PbVsUFpI3PJnQutg7bB1tj2zpUrQBHtZSozEZgSywW +Zatw8RB8uKxf/Z5cLCXK70liCwQ9kT7foYSeUGxl9sI2m1abmEVCGAVl0VT9Or+DwW1uGJEiGjIg +o/Wv4PfxEgpGUsn7dB6nHXbXPALwKRa68VFno06t0gabQWfdjlI= -MIIDdTCCAl2gAwIBAgICaFYwDQYJKoZIhvcNAQELBQAwXjEaMBgGA1UECgwRVGl6ZW4gQXNzb2Np -YXRpb24xGjAYBgNVBAsMEVRpemVuIEFzc29jaWF0aW9uMSQwIgYDVQQDDBtUaXplbiBEZXZlbG9w -ZXJzIFJvb3QgQ2xhc3MwHhcNMTUwMjEwMDEwNDAxWhcNMzAwMjA2MDEwNDAxWjCBijELMAkGA1UE -BhMCS1IxFDASBgNVBAgTC1NvdXRoIEtvcmVhMQ4wDAYDVQQHEwVTdXdvbjEmMCQGA1UEChMdU2Ft -c3VuZyBFbGVjdHJvbmljcyBDby4sIEx0ZC4xCzAJBgNVBAsTAlZEMSAwHgYDVQQDExdTYW1zdW5n -IEF1dGhvciBDQSBDbGFzczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK/iLAudLDIH -Xfqj5iLi/Izdo4rXMUdbkXYu9az9TgGfUqOmJi203kFFG1T5TQJfVMaBvry+MKLYPzIUWsTcrjel -DYVTWmEMucxm1lJvX0drZfXdi/EK7TzWEr0sR7ZR4cQuMgv80edK+H0ppFturPumrh/u8yVqTIHQ -QhfYbOIjW4939BdO5IG03F+8SrN5Udoe/YCtKPS3najZRxx3WqITVvV3AEKd2CualD/9y4Y+y+V7 -m90habypqWX2rnoMk5AG86wFyADkzEv0zoIve//atS2cHRGJx7Com/XXU8OBSsDavwf+6h5AVRzr -9ETcPTYoRrqt0g5h++xyckvGJKcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsF -AAOCAQEAM4cZsU/keJf7D7blzloKbt2a+iuVs6AVR0P/OjB49vmFyozm8oZRcWmxzFSb4+yz5GOj -CZtpynKgJWfQzL8JZ8zJW8OfMznRFn+sGDMvX3XsDrKkwsrtV0rs5E8WMqYmvH1TmFI9SvP3wgV/ -nKObF2mgyzZC+czZsfUSyNSJxOduNreLA111I7Zyibq+ulwrEs9EltuetBDih2g6XXH60ggXAr7m -yuCgfn8IW6zSZB3oA0Vc/CIOP9UEfm0LhrW28RgtDMWOXz8QygtMoKZ6R9TrG9S7cJP0rWeZisyQ -7LE4Aasrk7HNYn1Be+g2m4cUTvs6fLLwyQpARYZJwRHBMg== +MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMRowGAYDVQQKDBFUaXplbiBBc3NvY2lh +dGlvbjEaMBgGA1UECwwRVGl6ZW4gQXNzb2NpYXRpb24xHjAcBgNVBAMMFVRpemVuIERldmVsb3Bl +cnMgUm9vdDAeFw0xMjAxMDEwMDAwMDBaFw0yNzAxMDEwMDAwMDBaMFYxGjAYBgNVBAoMEVRpemVu +IEFzc29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4g +RGV2ZWxvcGVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVGhRGmMIUyBA7o +PCz8Sxut6z6HNkF4oDIuzuKaMzRYPeWodwe9O0gmqAkToQHfwg2giRhE5GoPld0fq+OYMMwSasCu +g8dwODx1eDeSYVuOLWRxpAmbTXOsSFi6VoWeyaPEm18JBHvZBsU5YQtgZ6Kp7MqzvQg3pXOxtajj +vyHxiatJl+xXrHgcXC1wgyG3buty7u/Fi2mvKXJ0PRJcCjjK81dqe/Vr20sRUCrbk02zbm5ggFt/ +jIEhV8wbFRQpliobc7J4dSTKhFfrqGM8rdd54LYhD7gSI1CFSe16pUXfcVR7FhJztRaiGLnCrwBE +dyTZ248+D4L/qR/D0axb3jcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC +AQEAnOXXQ/1O/QTDHyrmQDtFziqPY3xWlJBqJtEqXiT7Y+Ljpe66e+Ee/OjQMlZe8gu21/8cKklH +95RxjopMWCVedXDUbWdvS2+CdyvVW/quT2E0tjqIzXDekUTYwwhlPWlGxvfj3VsxqSFq3p8Brl04 +1Gx5RKAGyKVsMfTLhbbwSWwApuBUxYfcNpKwLWGPXkysu+HctY03OKv4/xKBnVWiN8ex/Sgesi0M ++OBAOMdZMPK32uJBTeKFx1xZgTLIhk45V0hPOomPjZloiv0LSS11eyd451ufjW0iHRE7WlpR6EvI +W6TFyZgMpQq+kg4hWl2SBTf3s2VI8Ygz7gj8TMlClg== diff --git a/Toolset/Tizen/BasicUI/.sign/signature1.xml b/Toolset/Tizen/BasicUI/.sign/signature1.xml index 43ce078..63c4d3c 100644 --- a/Toolset/Tizen/BasicUI/.sign/signature1.xml +++ b/Toolset/Tizen/BasicUI/.sign/signature1.xml @@ -9,13 +9,13 @@ NXzDtaWCXw== -M/eFnHFi2g/GYv0/D2hsHUZDLs9J1DZjCANuMtBFImSPGBr8F6JadxBVou43O8wyeEacadF9ZDG9 -5prLXzM+gg== +d49WGJ3MjEY0kD9IHGog/wEPNo2zS1s5pHer6i1FM2dZalIHsRuRsAVGlVxlXM5pFSCkp9kxWf5L +1J59A2Tfgw== -nsWBkoKSk7r0pu0ubb37gDanmRdIYcujiTiy0EErZP7ExRQajQE00K+sneKa8eSSOxH0OOecX9Ip -X++l2ykBJA== +PRuz95KE2QodgYrVJWPvkcWMK+Y6ykfDlRjDrXdQw2vlrXdd/T/W++TTRz1pJ0LTem6M0LjxTrSS +20iJYH+sLA== @@ -52,52 +52,40 @@ GyvKX9Snig== -h/6uo1RBmf2PcDwFShF1rJktgYolWJ+6oAfNxWnQaOAR4aITvD5BLGIXwA9JHLQXTtByBP2q8ODd -QUBGPXZLz67cHdzuWVHNgcb8FSuiHZzYXsCRKmgwj5BN24PHe41bZ/TSQejJTsPgTZ5R3jiOMTzP -gY67phZ7QCWj515gYvvWA4Y7Y888HbJpGFx8oStRRPl0hTLkr4dcOOMpX5XTABI2KTqNWDReiTUy -ulOE6MsdrtHEip6BynRvSgQJOGf9+iWjFm65LlHGt4G9WcVErPfhVNxXjgcxspL9ovo+vCZDSOP8 -E0f5jOAM6pxBSIilM1tUg4jlcywzoNe2pSj4KQ== +YiUEi2AHQ7GtltquG6Y6TdXKQA/CtYYWtYnsO1CEpbq5oX0gQRN6RI2jrNoktuHyzZkL+jZOs7wL +dghXMoY89v4PSce418R+sQ0VHmgSfMGVdJm9vE9pKXyb6upCi+5dfNRrcUSqY7u5U6YZmcczJmnR +lStlx/B4VIzVSDs3vhE= -MIID4zCCAsugAwIBAgIBZDANBgkqhkiG9w0BAQ0FADCBjzELMAkGA1UEBhMCS1IxFDASBgNVBAgM -C1NvdXRoIEtvcmVhMQ4wDAYDVQQHDAVTdXdvbjEmMCQGA1UECgwdU2Ftc3VuZyBFbGVjdHJvbmlj -cyBDby4sIEx0ZC4xCzAJBgNVBAsMAlZEMSUwIwYDVQQDDBxWRCBERVZFTE9QRVIgUHVibGljIENB -IENsYXNzMB4XDTI1MDcwMzE1MzExNFoXDTI2MDcwMzE1MzExNFowcTERMA8GA1UEAwwIVGl6ZW5T -REsxCTAHBgNVBAsMADEJMAcGA1UECgwAMQkwBwYDVQQHDAAxCTAHBgNVBAgMADEJMAcGA1UEBhMA -MSUwIwYJKoZIhvcNAQkBFhZqc2phcmRpbmVpcm9AZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAwxqNIiL0PS/WtelG8kXZf0pehwiIodi+QOdNedi32clrSHYoGJr8yaDA -pqx9g2LRWDJM1Av9iBNz89n4GZX3HUqPSbdKmV/k0jO7OoHOXPVDbus7uIlbG/9y4kZtXx/OTKSa -XX5nThSbknwP/qQcsA+H/MSuj0zgE+40scLd72kH3NU0xAg40tdB6J7EemodOkxxQPAWXD42nNAu -KLn25sALITwpuQDBXrqPcF3496jXMStGKHYxCpObkv+4rSd8P0s5hVhX5+j1Xr8FfjCgabGK575a -zIzc+orZIBvDbLut6kyLWhbbzeog0YIuh53f3+YlPE1KAPm4X2nWpBxLFwIDAQABo2cwZTBjBgNV -HREEXDBahhRVUk46dGl6ZW46cGFja2FnZWlkPYYgVVJOOnRpemVuOmRldmljZWlkPVhUQ2pZalpY -WkJaVkuGIFVSTjp0aXplbjpkZXZpY2VpZD1YVENKWUpaWFpCWlZLMA0GCSqGSIb3DQEBDQUAA4IB -AQAJ13iGnABSVF0carYNY6DjVaazKfMpg9B30CqHz8+2IpYLhaZuN4sW5cYpA5cIb6gjbRdyCGrc -ly5YSkhd61pjeV/Lclw9+Sp0YQQ6RkYSJqLQKrRKwo3XluEGe2Yhrj3uliDAESzdtf0fVqWx+NHI -5lSsFwS1wILJ6ovPYllWzC1VYrukf6z+yZLaFdBHYAygFRzNrQjDVnsO7kGW264uULN/csop3TcO -xcPb3yi7dWbZjgKpZnNurpx8C3UEtQ4CbPL6HtvDemeEP94qDLLsUyZHwt4QaxJae8Yygs6o3L6j -ja2S8auhtN2yclvvIl1/hblxvX4+vmwNQ2bc9p6E +MIICmzCCAgQCCQDXI7WLdVZwiTANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMCS1IxDjAMBgNV +BAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6ZW4gVGVzdCBDQTEiMCAGA1UE +CwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwbVGl6ZW4gUHVibGljIERpc3Ry +aWJ1dG9yIENBMB4XDTEyMTAyOTEzMDMwNFoXDTIyMTAyNzEzMDMwNFowgZMxCzAJBgNVBAYTAktS +MQ4wDAYDVQQIDAVTdXdvbjEOMAwGA1UEBwwFU3V3b24xFjAUBgNVBAoMDVRpemVuIFRlc3QgQ0Ex +IjAgBgNVBAsMGVRpemVuIERpc3RyaWJ1dG9yIFRlc3QgQ0ExKDAmBgNVBAMMH1RpemVuIFB1Ymxp +YyBEaXN0cmlidXRvciBTaWduZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALtMvlc5hENK +90ZdA+y66+Sy0enD1gpZDBh5T9RP0oRsptJv5jjNTseQbQi0SZOdOXb6J7iQdlBCtR343RpIEz8H +mrBy7mSY7mgwoU4EPpp4CTSUeAuKcmvrNOngTp5Hv7Ngf02TTHOLK3hZLpGayaDviyNZB5PdqQdB +hokKjzAzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAvGp1gxxAIlFfhJH1efjb9BJK/rtRkbYn9+Ez +GEbEULg1svsgnyWisFimI3uFvgI/swzr1eKVY3Sc8MQ3+Fdy3EkbDZ2+WAubhcEkorTWjzWz2fL1 +vKaYjeIsuEX6TVRUugHWudPzcEuQRLQf8ibZWjbQdBmpeQYBMg5x+xKLCJc= -MIIDrTCCApWgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UEBhMCS1IxFDASBgNVBAgM -C1NvdXRoIEtvcmVhMQ4wDAYDVQQHDAVTdXdvbjEmMCQGA1UECgwdU2Ftc3VuZyBFbGVjdHJvbmlj -cyBDby4sIEx0ZC4xCzAJBgNVBAsMAlZEMScwJQYDVQQDDB5WRCBERVZFTE9QRVIgUHVibGljIFJv -b3QgQ2xhc3MwHhcNMTQxMjE5MDkyOTQyWhcNMjkxMjE1MDkyOTQyWjCBjzELMAkGA1UEBhMCS1Ix -FDASBgNVBAgMC1NvdXRoIEtvcmVhMQ4wDAYDVQQHDAVTdXdvbjEmMCQGA1UECgwdU2Ftc3VuZyBF -bGVjdHJvbmljcyBDby4sIEx0ZC4xCzAJBgNVBAsMAlZEMSUwIwYDVQQDDBxWRCBERVZFTE9QRVIg -UHVibGljIENBIENsYXNzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr9u+prHP0MtG -DqQmDtIpFuFKD1mCmYPEA4OZ6zRH3f3t9cUmXtmAGEDPinCHpw9UdGU3JkNnNUd6dFf2HkFBIm8+ -LepRxR/rEmkHsBHFaLbTDVNZnwBXVs82eyMl9wonLp74otysnLAtEA968r7MH5WwwkF73W2vtOqA -+PpGOH31LAeLFNPajAVCgqiaIKn8eFQuLta2dNrXcZXia+GTXz0PZ0oEs6k1cphhkbe+uV5NL/qW -DjF5X1rIGxz/58AwxfF73wP7QPY9Z34vwai0tcUvGAkNXW60FjTj6iZ2N/UxPsuhNa1sSv2srxhW -SBAklC3L4A9C6o8sP91WkkdXIQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA -A4IBAQCnzmtVT7Zr8BjemLmZu/mLmGizAl/QaufSyCLaPVnUlgdReeMdjBvtvNlM9/EJecxiWhAa -kiZFA664lisAjQjL3bREP9HjOSSDhvx8GNLigjRKOJVivFxz0E4C7K/d9wBlstNCsTe2dRW0mhV+ -7l1kvbqByfi3kzUrJxaTOev/DxaPs9qofe/+Fvor5AcQXiKJ7wuva5HvYZq1z3f3XuEy/tIhv2fk -to09aZTNHNjeHeqiAUQFNrtv8NbHQZZKKaZQbnrT2h4HjtfuzAHaFt1EaO7l2TRE+OEJIpSkKT08 -1kT1zqSmnj38acW/+ExcY7fABrT3oigLsXPBsYxjSAtn +MIICtDCCAh2gAwIBAgIJAMDbehElPNKvMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJLUjEO +MAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSMw +IQYDVQQLDBpUVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEpMCcGA1UEAwwgVGl6ZW4gUHVibGlj +IERpc3RyaWJ1dG9yIFJvb3QgQ0EwHhcNMTIxMDI5MTMwMjUwWhcNMjIxMDI3MTMwMjUwWjCBjzEL +MAkGA1UEBhMCS1IxDjAMBgNVBAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6 +ZW4gVGVzdCBDQTEiMCAGA1UECwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTEkMCIGA1UEAwwb +VGl6ZW4gUHVibGljIERpc3RyaWJ1dG9yIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe +OTS/3nXvkDEmsFCJIvRlQ3RKDcxdWJJp625pFqHdmoJBdV+x6jl1raGK2Y1sp2Gdvpjc/z92yzAp +bE/UVLPh/tRNZPeGhzU4ejDDm7kzdr2f7Ia0U98K+OoY12ucwg7TYNItj9is7Cj4blGfuMDzd2ah +2AgnCGlwNwV/pv+uVQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACqJ +KO33YdoGudwanZIxMdXuxnnD9R6u72ltKk1S4zPfMJJv482CRGCI4FK6djhlsI4i0Lt1SVIJEed+ +yc3qckGm19dW+4xdlkekon7pViEBWuyHw8OWv3RXtTum1+PGHjBJ2eYY4ZKIpz73U/1NC16sTB/0 +VhfnkHwPltmrpYVe diff --git a/Toolset/Tizen/BasicUI/config.xml b/Toolset/Tizen/BasicUI/config.xml index 3e5b15b..e2879df 100644 --- a/Toolset/Tizen/BasicUI/config.xml +++ b/Toolset/Tizen/BasicUI/config.xml @@ -2,12 +2,15 @@ - + BasicUI - - - + + + + + + diff --git a/Toolset/Tizen/BasicUI/index.html b/Toolset/Tizen/BasicUI/index.html index ba401ca..51e4765 100755 --- a/Toolset/Tizen/BasicUI/index.html +++ b/Toolset/Tizen/BasicUI/index.html @@ -1,5 +1,5 @@ - + @@ -8,22 +8,28 @@ Tizen Mobile Web Basic Application - + - -
-
- Basic -
-
-
+ +
- - - - - - diff --git a/Toolset/Tizen/BasicUI/index_min_test.html b/Toolset/Tizen/BasicUI/index_min_test.html new file mode 100755 index 0000000..723789d --- /dev/null +++ b/Toolset/Tizen/BasicUI/index_min_test.html @@ -0,0 +1,73 @@ + + + + + Tizen AVPlay Minimal (Official Object) + + + +
+ +
+ + + \ No newline at end of file diff --git a/Toolset/Tizen/DUIDs.txt b/Toolset/Tizen/DUIDs.txt new file mode 100644 index 0000000..c770092 --- /dev/null +++ b/Toolset/Tizen/DUIDs.txt @@ -0,0 +1 @@ +8e961301-1a56-4a69-ad97-a82e65bd4a3e \ No newline at end of file diff --git a/Toolset/WebOS/HostedWebApp-main/index.html b/Toolset/WebOS/HostedWebApp-main/index.html index 47ee0db..2b60196 100644 --- a/Toolset/WebOS/HostedWebApp-main/index.html +++ b/Toolset/WebOS/HostedWebApp-main/index.html @@ -1,9 +1,11 @@ - + + + diff --git a/Toolset/WebOS/HostedWebApp-main/webOSTV-dev.js b/Toolset/WebOS/HostedWebApp-main/webOSTV-dev.js new file mode 100644 index 0000000..ce7ad90 --- /dev/null +++ b/Toolset/WebOS/HostedWebApp-main/webOSTV-dev.js @@ -0,0 +1 @@ +!function(){"use strict";var e={d:function(r,t){for(var n in t)e.o(t,n)&&!e.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},o:function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},r:function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},r={};function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t(e)}function n(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function o(e,r){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:function(){},r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){},t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"";if(!this.cancelled){var o={};try{o=JSON.parse(n)}catch(e){o={errorCode:-1,errorText:n,returnValue:!1}}var i=o,u=i.errorCode,c=i.returnValue;u||!1===c?(o.returnValue=!1,r(o)):(o.returnValue=!0,e(o)),t(o),this.subscribe||this.cancel()}}},{key:"cancel",value:function(){this.cancelled=!0,null!==this.bridge&&(this.bridge.cancel(),this.bridge=null),this.ts&&u[this.ts]&&delete u[this.ts]}}],r&&o(e.prototype,r),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,r}(),a={BROWSER:"APP_BROWSER"},s=function(e){var r=e.id,t=void 0===r?"":r,n=e.params,o=void 0===n?{}:n,i=e.onSuccess,u=void 0===i?function(){}:i,s=e.onFailure,l=void 0===s?function(){}:s,f={id:t,params:o};a.BROWSER===t&&(f.params.target=o.target||"",f.params.fullMode=!0,f.id="com.webos.app.browser"),function(e){var r=e.parameters,t=e.onSuccess,n=e.onFailure;(new c).send({service:"luna://com.webos.applicationManager",method:"launch",parameters:r,onComplete:function(e){var r=e.returnValue,o=e.errorCode,i=e.errorText;return!0===r?t():n({errorCode:o,errorText:i})}})}({parameters:f,onSuccess:u,onFailure:l})},l=function(){var e={};if(window.PalmSystem&&""!==window.PalmSystem.launchParams)try{e=JSON.parse(window.PalmSystem.launchParams)}catch(e){console.error("JSON parsing error")}return e},f=function(){return window.PalmSystem&&window.PalmSystem.identifier?window.PalmSystem.identifier.split(" ")[0]:""};function d(e){return d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},d(e)}function b(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function v(e){for(var r=1;r0&&void 0!==arguments[0]?arguments[0]:function(){},r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};setTimeout((function(){return e(r)}),0)},S=function(e){return 2===e.state&&""!==e.getClientId()},w=function(e,r){var t=r.errorCode,n=void 0===t?y.UNKNOWN_ERROR:t,o=r.errorText,i={errorCode:n,errorText:void 0===o?"Unknown error.":o};return e.setError(i),i},P={errorCode:y.CLIENT_NOT_LOADED,errorText:"DRM client is not loaded."},T=function(){return e=function e(r){!function(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}(this,e),this.clientId="",this.drmType=r,this.errorCode=y.NOT_ERROR,this.errorText="",this.state=0},(r=[{key:"getClientId",value:function(){return this.clientId}},{key:"getDrmType",value:function(){return this.drmType}},{key:"getErrorCode",value:function(){return this.errorCode}},{key:"getErrorText",value:function(){return this.errorText}},{key:"setError",value:function(e){var r=e.errorCode,t=e.errorText;this.errorCode=r,this.errorText=t}},{key:"isLoaded",value:function(e){var r=this,t=e.onSuccess,n=void 0===t?function(){}:t,o=e.onFailure,i=void 0===o?function(){}:o;O({method:"isLoaded",parameters:{appId:f()},onComplete:function(e){if(!0===e.returnValue){if(r.clientId=e.clientId||"",r.state=e.loadStatus?2:0,!0===e.loadStatus&&e.drmType!==r.drmType)return i(w(r,{errorCode:y.UNKNOWN_ERROR,errorText:"DRM types of set and loaded are not matched."}));var t=v({},e);return delete t.returnValue,n(t)}return i(w(r,e))}})}},{key:"load",value:function(e){var r=this,t=e.onSuccess,n=void 0===t?function(){}:t,o=e.onFailure,i=void 0===o?function(){}:o;if(1!==this.state&&2!==this.state){var u={appId:f(),drmType:this.drmType};this.state=1,O({method:"load",onComplete:function(e){return!0===e.returnValue?(r.clientId=e.clientId,r.state=2,n({clientId:r.clientId})):i(w(r,e))},parameters:u})}else g(n,{isLoaded:!0,clientId:this.clientId})}},{key:"unload",value:function(e){var r=this,t=e.onSuccess,n=void 0===t?function(){}:t,o=e.onFailure,i=void 0===o?function(){}:o;if(S(this)){var u={clientId:this.clientId};this.state=3,O({method:"unload",onComplete:function(e){return!0===e.returnValue?(r.clientId="",r.state=0,n()):i(w(r,e))},parameters:u})}else g(i,w(this,P))}},{key:"getRightsError",value:function(e){var r=this,t=e.onSuccess,n=void 0===t?function(){}:t,o=e.onFailure,i=void 0===o?function(){}:o;S(this)?O({method:"getRightsError",parameters:{clientId:this.clientId,subscribe:!0},onComplete:function(e){if(!0===e.returnValue){var t=v({},e);return delete t.returnValue,n(t)}return i(w(r,e))}}):g(i,w(this,P))}},{key:"sendDrmMessage",value:function(e){var r=this,t=e.msg,n=void 0===t?"":t,o=e.onSuccess,i=void 0===o?function(){}:o,u=e.onFailure,c=void 0===u?function(){}:u;if(S(this)){var a=function(e){var r="",t="";switch(e){case h.PLAYREADY:r="application/vnd.ms-playready.initiator+xml",t="urn:dvb:casystemid:19219";break;case h.WIDEVINE:r="application/widevine+xml",t="urn:dvb:casystemid:19156"}return{msgType:r,drmSystemId:t}}(this.drmType),s=v({clientId:this.clientId,msg:n},a);O({method:"sendDrmMessage",onComplete:function(e){if(!0===e.returnValue){var t=v({},e);return delete t.returnValue,i(t)}return c(w(r,e))},parameters:s})}else g(c,w(this,P))}}])&&p(e.prototype,r),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,r}(),j={Error:y,Type:h},E=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return""===e?null:new T(e)};function D(e){return D="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},D(e)}function I(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}var R={getStatus:function(e){var r=e.onSuccess,t=void 0===r?function(){}:r,n=e.onFailure,o=void 0===n?function(){}:n,i=e.subscribe,u=void 0!==i&&i,a="webos.service";navigator.userAgent.indexOf("537.41")>-1&&(a="palm"),function(e){var r=e.service,t=e.subscribe,n=e.onSuccess,o=e.onFailure;(new c).send({service:r,method:"getStatus",parameters:{subscribe:t},onComplete:function(e){var r=function(e){for(var r=1;r=200&&i.status<300||0===i.status?r(null,i.responseText):r({status:404}))};try{i.open("GET",n||"appinfo.json",!0),i.send(null)}catch(e){r({status:404})}}else e&&e(o)},i=function(){var e=window.location.href;if("baseURI"in window.document)e=window.document.baseURI;else{var n=window.document.getElementsByTagName("base");n.length>0&&(e=n[0].href)}var t=e.match(/.*:\/\/[^#]*\//);return t?t[0]:""},s=function(){if(window.PalmSystem&&window.PalmSystem.platformBack)return window.PalmSystem.platformBack()};function u(e){return u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u(e)}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function c(e){for(var n=1;n0&&void 0!==arguments[0]?arguments[0]:function(){},n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){},t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"";if(!this.cancelled){var r={};try{r=JSON.parse(o)}catch(e){r={errorCode:-1,errorText:o,returnValue:!1}}var i=r,s=i.errorCode,u=i.returnValue;s||!1===u?(r.returnValue=!1,n(r)):(r.returnValue=!0,e(r)),t(r),this.subscribe||this.cancel()}}},{key:"cancel",value:function(){this.cancelled=!0,null!==this.bridge&&(this.bridge.cancel(),this.bridge=null),this.ts&&f[this.ts]&&delete f[this.ts]}}],n&&l(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,n}(),p={request:function(){var e=c({service:arguments.length>0&&void 0!==arguments[0]?arguments[0]:""},arguments.length>1&&void 0!==arguments[1]?arguments[1]:{});return(new m).send(e)}},v=p;function y(e){return y="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},y(e)}var g={};if("object"===("undefined"==typeof window?"undefined":y(window))&&window.PalmSystem){if(window.navigator.userAgent.indexOf("SmartWatch")>-1)g.watch=!0;else if(window.navigator.userAgent.indexOf("SmartTV")>-1||window.navigator.userAgent.indexOf("Large Screen")>-1)g.tv=!0;else{try{var w=JSON.parse(window.PalmSystem.deviceInfo||"{}");if(w.platformVersionMajor&&w.platformVersionMinor){var b=Number(w.platformVersionMajor),h=Number(w.platformVersionMinor);b<3||3===b&&h<=0?g.legacy=!0:g.open=!0}}catch(e){g.open=!0}window.Mojo=window.Mojo||{relaunch:function(){}},window.PalmSystem.stageReady&&window.PalmSystem.stageReady()}if(window.navigator.userAgent.indexOf("Chr0me")>-1||window.navigator.userAgent.indexOf("Chrome")>-1){var S=window.navigator.userAgent.indexOf("Chr0me")>-1?window.navigator.userAgent.indexOf("Chr0me"):window.navigator.userAgent.indexOf("Chrome"),O=window.navigator.userAgent.slice(S).indexOf(" "),V=window.navigator.userAgent.slice(S+7,S+O).split(".");g.chrome=Number(V[0])}else g.chrome=0}else g.unknown=!0;var T=g,P={},k={},j=!1,A=!1,D=!1,C=[];function x(e){A&&D?(C.length&&(C.forEach((function(n){n!==e&&n(P)})),C=[]),e(P)):C.push(e)}function M(e){k.soundOutput&&0===k.soundOutput.indexOf("external_arc")&&"external_arc_sound_alive"!==k.soundOutput?e(!0):!k.soundOutput||0!==k.soundOutput.indexOf("tv_")&&"external_arc_sound_alive"!==k.soundOutput?e(null):e(!1)}function N(e){"auto"===k.soundOutputDigital||"passThrough"===k.soundOutputDigital?e(!0):e(!1)}function _(e,n){P.dolbyAtmos!==e&&(P.dolbyAtmos=e,A=!0,x(n))}function B(e){!function(e){P.sdkVersion&&e(P.sdkVersion.split(".")),(new m).send({service:"luna://com.webos.service.tv.systemproperty",method:"getSystemInfo",parameters:{keys:["sdkVersion"]},onSuccess:function(n){P.sdkVersion=n.sdkVersion||P.sdkVersion,e(P.sdkVersion.split("."))},onFailure:function(){e([0,0,0])}})}((function(n){parseInt(n[0],10)>=5?(new m).send({service:"luna://com.webos.service.arccontroller",method:"getARCState",subscribe:!0,onComplete:function(n){M((function(t){(t||!k.dolbyAtmosConfig&&"tv_speaker_external_arc_harmony"===k.soundOutput)&&N((function(t){_(!!t&&n.returnValue&&("ATMOS"===n.arcProfile||!0===n.earcATMOS),e)}))}))},onFailure:function(){console.log("[webOSTV.js] getARCState failed"),_(!1,e)}}):(new m).send({service:"luna://com.webos.service.eim",method:"getAllInputStatus",subscribe:!0,onComplete:function(n){M((function(t){!t&&(k.dolbyAtmosConfig||"tv_speaker_external_arc_harmony"!==k.soundOutput&&void 0!==k.soundOutput)||N((function(t){_(!!t&&n.returnValue&&!0===n.atmosDevice,e)}))}))},onFailure:function(){console.log("[webOSTV.js] getAllInputStatus failed"),_(!1,e)}})}))}function R(e){void 0===k.dolbyAtmosConfig?(new m).send({service:"luna://com.webos.service.config",method:"getConfigs",parameters:{configNames:["tv.config.supportDolbyTVATMOS","tv.model.soundModeType"]},onComplete:function(n){k.dolbyAtmosConfig=n.configs?n.configs["tv.config.supportDolbyTVATMOS"]||"Dolby Atmos"===n.configs["tv.model.soundModeType"]:"failure",R(e)}}):!0===k.dolbyAtmosConfig?_(!0,e):!1===k.dolbyAtmosConfig?"tv_speaker_external_arc_harmony"===k.soundOutput?N((function(n){n?B(e):_(!1,e)})):void 0===k.soundOutput?(console.log("[webOSTV.js] soundOutput value is",k.soundOutput),B(e)):_(!1,e):(console.log("[webOSTV.js] dolbyAtmos config is",k.dolbyAtmosConfig),_(!1,e))}var z=function(e){!function(e){(new m).send({service:"luna://com.webos.settingsservice",method:"getSystemSettings",parameters:{category:"sound",keys:["soundOutput","soundOutputDigital"]},subscribe:!0,onSuccess:function(n){n.settings?(k.soundOutput=n.settings.soundOutput||k.soundOutput,k.soundOutputDigital=n.settings.soundOutputDigital||k.soundOutputDigital,n.settings.soundOutput?(k.soundOutput=n.settings.soundOutput,M((function(n){n?N((function(n){n?B(e):_(!1,e)})):!1===n?R(e):_(!1,e)}))):n.settings.soundOutputDigital&&M((function(n){(n||"tv_speaker_external_arc_harmony"===k.soundOutput&&!0!==k.dolbyAtmosConfig)&&N((function(n){n?B(e):_(!1,e)}))}))):_(!1,e)},onFailure:function(){console.log("[webOSTV.js] getSystemSettings(soundOutput) failed"),R(e)}})}(e),j?x(e):(j=!0,function(){try{var e=JSON.parse(window.PalmSystem.deviceInfo);P.modelName=e.modelName,P.version=e.platformVersion,P.versionMajor=e.platformVersionMajor,P.versionMinor=e.platformVersionMinor,P.versionDot=e.platformVersionDot,P.screenWidth=e.screenWidth,P.screenHeight=e.screenHeight}catch(e){P.modelName="webOS Device"}P.screenHeight=P.screenHeight||window.screen.height,P.screenWidth=P.screenWidth||window.screen.width}(),T.tv?(P.uhd=!1,P.uhd8K=!1,P.hdr10=!1,P.dolbyVision=!1,P.brandName="LG",P.manufacturer="LG Electronics",P.platformBizType="LG",P.tuner=!0,function(e){(new m).send({service:"luna://com.webos.service.config",method:"getConfigs",parameters:{configNames:["com.webos.app.home.uiStyle","com.webos.service.utp.supportTunerless","profile.list","tv.config.supportDolbyHDRContents","tv.hw.ddrSize","tv.hw.displayType","tv.hw.panelResolution","tv.model.mainboardMaker","tv.model.modelname","tv.model.supportHDR","tv.model.supportTemp8K","tv.model.TVBrandName","tv.model.TVManufacturer","tv.nyx.firmwareVersion","tv.nyx.platformVersion","wee.platformBizType"]},onComplete:function(n){if(n.configs){if(P.modelName=n.configs["tv.model.modelname"]||P.modelName,n.configs["tv.nyx.firmwareVersion"]&&"0.0.0"!==n.configs["tv.nyx.firmwareVersion"]||(n.configs["tv.nyx.firmwareVersion"]=n.configs["tv.nyx.platformVersion"]),n.configs["tv.nyx.firmwareVersion"]){P.version=n.configs["tv.nyx.firmwareVersion"];for(var t=P.version.split("."),o=["versionMajor","versionMinor","versionDot"],r=0;r + + + + Title + + + + +

Hello world

+
+ + + + + + + + + + +

Logs

+
+ + + + \ No newline at end of file diff --git a/demo/dash_widevine_vod.html b/demo/dash_widevine_vod.html new file mode 100644 index 0000000..b8e7f27 --- /dev/null +++ b/demo/dash_widevine_vod.html @@ -0,0 +1,182 @@ + + + + + Title + + + + +

Hello world

+
+ + + + + + + + + + +

Logs

+
+ + + + \ No newline at end of file diff --git a/demo/index.html b/demo/index.html index 47dfea7..1208c07 100644 --- a/demo/index.html +++ b/demo/index.html @@ -1,14 +1,14 @@ - + Title - +

Hello world

-
+
diff --git a/demo/index_dash_widevine_live_voka.html b/demo/index_dash_widevine_live_voka.html index 94ecb21..d4a9b89 100644 --- a/demo/index_dash_widevine_live_voka.html +++ b/demo/index_dash_widevine_live_voka.html @@ -29,7 +29,6 @@ movieId: null, episodeId: null, newsId: null, - apiHost: 'localhost:8080', }, uiConfig: { initAsLive: true diff --git a/demo/index_hls_fairplay_vod.html b/demo/index_hls_fairplay_vod.html index c0943db..b6b5ad5 100644 --- a/demo/index_hls_fairplay_vod.html +++ b/demo/index_hls_fairplay_vod.html @@ -9,7 +9,7 @@

Hello world

- Демка показывает возможность воспроизведения hls widevine vod + Демка показывает возможность воспроизведения hls fairplay vod

Исходник https://hlsjs.video-dev.org/demo/?src=https%3A%2F%2Fstorage.googleapis.com%2Fshaka-demo-assets%2Fangel-one-widevine-hls%2Fhls.m3u8&demoConfig=eyJlbmFibGVTdHJlYW1pbmciOnRydWUsImF1dG9SZWNvdmVyRXJyb3IiOnRydWUsInN0b3BPblN0YWxsIjpmYWxzZSwiZHVtcGZNUDQiOmZhbHNlLCJsZXZlbENhcHBpbmciOi0xLCJsaW1pdE1ldHJpY3MiOi0xfQ== @@ -29,7 +29,6 @@ movieId: null, episodeId: null, newsId: null, - apiHost: 'localhost:8080', }, uiConfig: { initAsLive: true diff --git a/demo/index_hls_widevine_vod.html b/demo/index_hls_widevine_vod.html index f6f2832..5352b96 100644 --- a/demo/index_hls_widevine_vod.html +++ b/demo/index_hls_widevine_vod.html @@ -29,7 +29,6 @@ movieId: null, episodeId: null, newsId: null, - apiHost: 'localhost:8080', }, uiConfig: { initAsLive: true diff --git a/demo/index_web.html b/demo/index_web.html new file mode 100644 index 0000000..47dfea7 --- /dev/null +++ b/demo/index_web.html @@ -0,0 +1,182 @@ + + + + + Title + + + + +

Hello world

+
+ + + + + + + + + + +

Logs

+
+ + + + \ No newline at end of file diff --git a/demo/v1/channels/dash-playready-vod/stream.json b/demo/v1/channels/dash-playready-vod/stream.json new file mode 100644 index 0000000..3a912f4 --- /dev/null +++ b/demo/v1/channels/dash-playready-vod/stream.json @@ -0,0 +1,21 @@ +{ + "data": { + "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", + "drm": { + "type": "playready", + "license_server": "https://drm-playready-licensing.axtest.net/AcquireLicense" + }, + "adv1": "https://cdn.theoplayer.com/demos/ads/vmap/single-pre-mid-post-no-skip.xml", + "subtitles": "https://raw.githubusercontent.com/videojs/video.js/c7298d40a4632a6e9dfcd5a2f5cc3bbe92a78744/docs/examples/elephantsdream/captions.ru.vtt", + "analytics_v2": { + "url": "https://juraldinio.com/analytics/", + "interval": 5000, + "additional_parameters": { + "application_id": "42", + "user_id": "12321", + "resource_type": "video", + "watch_session_id": "100500" + } + } + } +} \ No newline at end of file diff --git a/demo/v1/channels/dash-widevine-live-voka/stream.json b/demo/v1/channels/dash-widevine-live-voka/stream.json index a9758b8..d6db742 100644 --- a/demo/v1/channels/dash-widevine-live-voka/stream.json +++ b/demo/v1/channels/dash-widevine-live-voka/stream.json @@ -1,6 +1,6 @@ { "data": { - "url": "https://streaming-iptv.voka.tv/eyJvc19uYW1lIjoibWFjIG9zIiwidXNlcl91aWQiOiIzMDE4ZmM2Yi02YmY4LTQ4OGQtOGRhMi02YjZmNWFmMjFjNDQiLCJkYXRhY2VudGVyIjoiaW50IiwiZG9tYWluX25hbWUiOiJzdHJlYW1pbmctaXB0di52b2thLnR2IiwiZHJtIjoid2lkZXZpbmUiLCJleHBpcmF0aW9uX2RhdGUiOiIyMDI1LTA3LTMxVDIwOjUxOjEzWiIsImlwX2FkZHJlc3MiOiIxODUuMTM1LjE1MC40MCIsInByb2plY3QiOiJ2b2thX3Byb2R1Y3Rpb24iLCJwcm90b2NvbCI6ImRhc2giLCJzZXNzaW9uX2lkIjoiM2MzYTkxMjMtY2VkZi00ODdmLWI4MzItZjhkYjNmNWZkMmY0Iiwic3RyZWFtX25hbWUiOiI1ODMiLCJzdHJlYW1fcGF0aCI6Ii9pcF92NSJ9/MCwCFAaa_NjyUSswHJxTYp3hATrVF-cFAhQFUugUrPqnUOYfpnkl5RuhIAcuSA%3D%3D/ip_v5/583.mpd?b_app_channel_id=7e8cedbe-5f18-4649-8468-dd5af597a670&b_app_id=voka_production&b_device_platform=mac%20os&b_device_uid=1d866e05-b0e5-e943-f49c-295ac85c20d7&b_stream_sid=3c3a9123-cedf-487f-b832-f8db3f5fd2f4&b_strmr_channel_id=583&stream_dvr_window=10800000000 ", + "url": "https://streaming-iptv.voka.tv/eyJvc19uYW1lIjoibWFjIG9zIiwidXNlcl91aWQiOiIzMDE4ZmM2Yi02YmY4LTQ4OGQtOGRhMi02YjZmNWFmMjFjNDQiLCJkYXRhY2VudGVyIjoiaW50IiwiZG9tYWluX25hbWUiOiJzdHJlYW1pbmctaXB0di52b2thLnR2IiwiZHJtIjoic3BidHZjYXMiLCJleHBpcmF0aW9uX2RhdGUiOiIyMDI1LTA4LTAzVDE3OjQxOjU0WiIsImlwX2FkZHJlc3MiOiI4OS4xMTAuMTIyLjE3NSIsInByb2plY3QiOiJ2b2thX3Byb2R1Y3Rpb24iLCJwcm90b2NvbCI6ImRhc2giLCJzZXNzaW9uX2lkIjoiNzkzNmJmY2EtZTA1ZS00NjJjLWE1MTQtZTU3NTk0MmY2ZDc2Iiwic3RyZWFtX25hbWUiOiI1ODMiLCJzdHJlYW1fcGF0aCI6Ii9pcF92NSJ9/MCwCFHXIZystCP_74eXig9GDBoGggAxjAhRGzvQFAovCN4VwluftKYV6tBmWFQ%3D%3D/ip_v5/583.mpd?b_app_channel_id=7e8cedbe-5f18-4649-8468-dd5af597a670&b_app_id=voka_production&b_device_platform=mac%20os&b_device_uid=1d866e05-b0e5-e943-f49c-295ac85c20d7&b_stream_sid=7936bfca-e05e-462c-a514-e575942f6d76&b_strmr_channel_id=583&stream_dvr_window=10800000000", "drm": { "type": "widevine", "license_server": "https://drmproxy.voka.tv" diff --git a/demo/v1/channels/dash-widevine-vod/stream.json b/demo/v1/channels/dash-widevine-vod/stream.json new file mode 100644 index 0000000..3e55077 --- /dev/null +++ b/demo/v1/channels/dash-widevine-vod/stream.json @@ -0,0 +1,22 @@ +{ + "data": { + "url-1": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", + "url": "https://media.axprod.net/TestVectors/Dash/protected_dash_1080p_h264_singlekey/manifest.mpd", + "drm": { + "type": "widevine", + "license_server": "https://drm-widevine-licensing.axtest.net/AcquireLicense" + }, + "adv1": "https://cdn.theoplayer.com/demos/ads/vmap/single-pre-mid-post-no-skip.xml", + "subtitles": "https://raw.githubusercontent.com/videojs/video.js/c7298d40a4632a6e9dfcd5a2f5cc3bbe92a78744/docs/examples/elephantsdream/captions.ru.vtt", + "analytics_v2": { + "url": "https://juraldinio.com/analytics/", + "interval": 5000, + "additional_parameters": { + "application_id": "42", + "user_id": "12321", + "resource_type": "video", + "watch_session_id": "100500" + } + } + } +} \ No newline at end of file diff --git a/demo/v1/channels/hls-998f5396-c9dd-4a1e-82c7-0aec531fc015/stream.json b/demo/v1/channels/hls-998f5396-c9dd-4a1e-82c7-0aec531fc015/stream.json index 110963c..dadfcb3 100644 --- a/demo/v1/channels/hls-998f5396-c9dd-4a1e-82c7-0aec531fc015/stream.json +++ b/demo/v1/channels/hls-998f5396-c9dd-4a1e-82c7-0aec531fc015/stream.json @@ -1,8 +1,26 @@ { "data": { "url2": "http://mirrors.standaloneinstaller.com/video-sample/jellyfish-25-mbps-hd-hevc.mp4", - "urlq": "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8", - "url": "https://cdn.bitmovin.com/content/assets/sintel/hls/playlist.m3u8", + "url-simple": "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/gear1/prog_index.m3u8", + "url": "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8", + "url-dash": "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd", + "url-blocked": "https://cdn.bitmovin.com/content/assets/sintel/hls/playlist.m3u8", + "url-hls-videwine-vod": "https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine-hls/hls.m3u8", + "drm-hls-videwine-vod": { + "type": "widevine", + "license_server": "https://cwip-shaka-proxy.appspot.com/no_auth" + }, + "dash-widevine": "mark", + "url-dash-widevine": "https://media.axprod.net/TestVectors/Dash/protected_dash_1080p_h264_singlekey/manifest.mpd", + "drm-dash-widevine": { + "type": "widevine", + "license_server": "https://drm-widevine-licensing.axtest.net/AcquireLicense" + }, + "drm-dash-playready": { + "type": "playready", + "license_server": "https://drm-playready-licensing.axprod.net/AcquireLicense" + }, + "url-hls-live": "https://dai.google.com/linear/hls/event/rtcMlf4RTvOEkaudeany5w/master.m3u8?iu=/4128/CBS.NY.OTT", "adv1": "https://cdn.theoplayer.com/demos/ads/vmap/single-pre-mid-post-no-skip.xml", "subtitles": "https://raw.githubusercontent.com/videojs/video.js/c7298d40a4632a6e9dfcd5a2f5cc3bbe92a78744/docs/examples/elephantsdream/captions.ru.vtt", "analytics_v2": { diff --git a/docker-compose.caddy.yml b/docker-compose.caddy.yml new file mode 100644 index 0000000..185c33c --- /dev/null +++ b/docker-compose.caddy.yml @@ -0,0 +1,45 @@ +version: '3.8' + +services: + server: + image: docker.io/library/voka-player + container_name: voka-player + environment: + - USER_UID=1000 + - USER_GID=1000 + restart: always + volumes: + - $PWD:/usr/voka + - node_modules:/usr/voka/node_modules + networks: + - web + labels: + - "traefik.enable=false" # просто чтобы избежать конфликтов + + caddy: + image: caddy:2 + container_name: caddy + restart: always + ports: + - "80:80" + - "443:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data + - caddy_config:/config + networks: + - web + +volumes: + node_modules: + driver: local + driver_opts: + type: none + o: bind + device: $PWD/node_modules + caddy_data: {} + caddy_config: {} + +networks: + web: + driver: bridge \ No newline at end of file diff --git a/src/assets/scss/components/_poster.scss b/src/assets/scss/components/_poster.scss index 4faf53d..b12e31a 100644 --- a/src/assets/scss/components/_poster.scss +++ b/src/assets/scss/components/_poster.scss @@ -1,5 +1,6 @@ .voka-poster { display: inline-block; + z-index: -1000; vertical-align: middle; background-repeat: no-repeat; background-position: 50% 50%; diff --git a/src/internal/drm/dash/VokaDash.ts b/src/internal/drm/dash/VokaDash.ts index df2c7d4..d1a45ce 100644 --- a/src/internal/drm/dash/VokaDash.ts +++ b/src/internal/drm/dash/VokaDash.ts @@ -12,7 +12,7 @@ import { MediaPlayerErrorEvent, QualityChangeRenderedEvent, Representation, StreamInitializedEvent, -} from 'dashjs' +} from "dashjs"; import { ComponentErrorInfo, VokaError, @@ -591,21 +591,11 @@ export default class VokaDash { view: any ): MediaPlayerClass { const mediaPlayer = MediaPlayer().create() - // For whatever reason, we need to call setTextDefaultEnabled(false) to get - // VTT captions to show, even though we're doing virtually the same thing - // in setup-text-tracks.js - // @TODO разобраться, почему нет такого метода - // mediaPlayer.setTextDefaultEnabled(false) - // mediaPlayer.extend('HTTPLoader', HTTPLoader, true) - - // Must run controller before these two lines or else there is no - // element to bind to. - mediaPlayer.initialize() + mediaPlayer.setProtectionData(keySystemOptions) this.attachListeners(mediaPlayer) - //Хотя что мы вообще собираемся посылать? // Apply all dash options that are set if (options) { Object.keys(options).forEach((key) => { @@ -632,17 +622,7 @@ export default class VokaDash { }) } - mediaPlayer.attachView(view) - - // Dash.js autoplays by default, video.js will handle autoplay - mediaPlayer.setAutoPlay(false) - - // Setup text tracks - //setupTextTracks.call(null, this.player, tech, options) - - // Attach the source with any protection data - mediaPlayer.setProtectionData(keySystemOptions) - mediaPlayer.attachSource(manifestSource) + mediaPlayer.initialize(view, manifestSource, false) this.player.trigger(VokaEvent.MasterDashPlaylistLoad, manifestSource) @@ -702,6 +682,14 @@ export default class VokaDash { this.setBufferingComplete, this ) + mediaPlayer.on( + 'public_keySystemSelected', + e => console.log("Key system selected: ", e), + ) + mediaPlayer.on( + 'public_keyAdded', + e => console.log("Key added:", e), + ) } private updateBufferingMode(value: boolean) { diff --git a/src/internal/player/VokaCorePlayer.ts b/src/internal/player/VokaCorePlayer.ts index cc7cd27..e3f8010 100755 --- a/src/internal/player/VokaCorePlayer.ts +++ b/src/internal/player/VokaCorePlayer.ts @@ -1,3 +1,9 @@ +import { + IVokaSource, + TizenSourceParams, + TizenSourceProtection, + WebOSSourceProtection, +} from "@/internal/player/native/VokaSourceHandler"; import videojs from 'video.js' import Player from 'video.js/dist/types/player' import chromecastPlugin from '@silvermine/videojs-chromecast/' @@ -251,80 +257,93 @@ namespace VokaCorePlayer { throw new Error('Empty content URL') } - let playableContent = null + const drmTypes = { + [DRMType.WIDEVINE]: 'com.widevine.alpha', + [DRMType.PLAYREADY]: 'com.microsoft.playready', + [DRMType.FAIRPLAY]: 'com.apple.fps', + } + let playableContent: IVokaSource = null const drm = content.drmConfig switch(content.type) { case VokaContentType.HLS: playableContent = { sourceType: "application/vnd.apple.mpegurl", - } + } as IVokaSource + if (!drm) break - switch (drm.type) { - case DRMType.WIDEVINE: - playableContent["drmSystems"] = { - 'com.widevine.alpha': { - licenseUrl: drm.certificateUrl, - } + const drmTypeString = drmTypes[drm.type] + if (!drmTypeString) break + + if (drm.type === DRMType.FAIRPLAY) { + // hls.js + playableContent.drmSystems = { + [drmTypeString]: { + certificateUrl: drm.certificateUrl, + licenseUrl: drm.licenseUrl } - break - case DRMType.PLAYREADY: - playableContent["drmSystems"] = { - 'com.microsoft.playready': { - licenseUrl: drm.certificateUrl, - } + } + } else { + // hls.js + playableContent.drmSystems = { + [drmTypeString]: { + licenseUrl: drm.certificateUrl } - break - // Подержка FP в hls.js - case DRMType.FAIRPLAY: - playableContent["drmSystems"] = { - 'com.apple.fps': { - certificateUrl: drm.certificateUrl, - licenseUrl: drm.licenseUrl, - } + } + // WebOS native + playableContent.webOSProtection = { + licenseServer: drm.certificateUrl + } as WebOSSourceProtection + // Tizen native + playableContent.tizenParams = { + protection: { + type: drm.type, + licenseServer: drm.certificateUrl } - break - } - break - case VokaContentType.MP4: - playableContent = { - sourceType: "video/mp4", + } as TizenSourceParams } break case VokaContentType.DASH: + case VokaContentType.WIDEVINE: + case VokaContentType.PLAYREADY: playableContent = { sourceType: "application/dash+xml", - } - break - case VokaContentType.WIDEVINE: - if (drm != null && drm.type == DRMType.WIDEVINE) { - playableContent = { - sourceType: "application/dash+xml", - keySystemOptions: [{ - name: "com.widevine.alpha", - options: { - serverURL: drm.certificateUrl, - httpRequestHeaders: drm.headers, - priority: 0, - } - }] - } - } - break - case VokaContentType.PLAYREADY: - if (drm != null && drm.type == DRMType.PLAYREADY) { - playableContent = { - sourceType: "application/dash+xml", - keySystemOptions: [{ - name: "com.microsoft.playready", - options: { - serverURL: drm.certificateUrl, - httpRequestHeaders: drm.headers, - priority: 0, - } - }] - } - } - break + } as IVokaSource; + + if (!drm) break; + const allowedDrmTypes = [DRMType.WIDEVINE, DRMType.PLAYREADY]; + + if (!allowedDrmTypes.includes(drm.type)) break; + // dash.js + playableContent.keySystemOptions = [{ + name: drmTypes[drm.type], + options: { + serverURL: drm.certificateUrl, + // Доп. заголовки, например, авторизация запсроса к серверу лицензий + // httpRequestHeaders: { + // "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJ2ZXJzaW9uIjogMSwKICAiY29tX2tleV9pZCI6ICI2OWU1NDA4OC1lOWUwLTQ1MzAtOGMxYS0xZWI2ZGNkMGQxNGUiLAogICJtZXNzYWdlIjogewogICAgInR5cGUiOiAiZW50aXRsZW1lbnRfbWVzc2FnZSIsCiAgICAidmVyc2lvbiI6IDIsCiAgICAibGljZW5zZSI6IHsKICAgICAgImFsbG93X3BlcnNpc3RlbmNlIjogdHJ1ZQogICAgfSwKICAgICJjb250ZW50X2tleXNfc291cmNlIjogewogICAgICAiaW5saW5lIjogWwogICAgICAgIHsKICAgICAgICAgICJpZCI6ICI0MDYwYTg2NS04ODc4LTQyNjctOWNiZi05MWFlNWJhZTFlNzIiLAogICAgICAgICAgImVuY3J5cHRlZF9rZXkiOiAid3QzRW51dVI1UkFybjZBRGYxNkNCQT09IiwKICAgICAgICAgICJ1c2FnZV9wb2xpY3kiOiAiUG9saWN5IEEiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgImNvbnRlbnRfa2V5X3VzYWdlX3BvbGljaWVzIjogWwogICAgICB7CiAgICAgICAgIm5hbWUiOiAiUG9saWN5IEEiLAogICAgICAgICJwbGF5cmVhZHkiOiB7CiAgICAgICAgICAibWluX2RldmljZV9zZWN1cml0eV9sZXZlbCI6IDE1MCwKICAgICAgICAgICJwbGF5X2VuYWJsZXJzIjogWwogICAgICAgICAgICAiNzg2NjI3RDgtQzJBNi00NEJFLThGODgtMDhBRTI1NUIwMUE3IgogICAgICAgICAgXQogICAgICAgIH0KICAgICAgfQogICAgXQogIH0KfQ.l8PnZznspJ6lnNmfAE9UQV532Ypzt1JXQkvrk8gFSRw" + // }, + httpRequestHeaders: drm.headers, + priority: 0, + }, + }, + ]; + // WebOS native + playableContent.webOSProtection = { + licenseServer: drm.certificateUrl, + } as WebOSSourceProtection; + // Tizen native + playableContent.tizenParams = { + protection: { + type: drm.type, + licenseServer: drm.certificateUrl, + // Доп. заголовки, например, авторизация запроса к серверу лицензий + // В виде строки, разделитель заголовков - \n + // httpHeader: + // "X-AxDRM-Message:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJ2ZXJzaW9uIjogMSwKICAiY29tX2tleV9pZCI6ICI2OWU1NDA4OC1lOWUwLTQ1MzAtOGMxYS0xZWI2ZGNkMGQxNGUiLAogICJtZXNzYWdlIjogewogICAgInR5cGUiOiAiZW50aXRsZW1lbnRfbWVzc2FnZSIsCiAgICAidmVyc2lvbiI6IDIsCiAgICAibGljZW5zZSI6IHsKICAgICAgImFsbG93X3BlcnNpc3RlbmNlIjogdHJ1ZQogICAgfSwKICAgICJjb250ZW50X2tleXNfc291cmNlIjogewogICAgICAiaW5saW5lIjogWwogICAgICAgIHsKICAgICAgICAgICJpZCI6ICI0MDYwYTg2NS04ODc4LTQyNjctOWNiZi05MWFlNWJhZTFlNzIiLAogICAgICAgICAgImVuY3J5cHRlZF9rZXkiOiAid3QzRW51dVI1UkFybjZBRGYxNkNCQT09IiwKICAgICAgICAgICJ1c2FnZV9wb2xpY3kiOiAiUG9saWN5IEEiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgImNvbnRlbnRfa2V5X3VzYWdlX3BvbGljaWVzIjogWwogICAgICB7CiAgICAgICAgIm5hbWUiOiAiUG9saWN5IEEiLAogICAgICAgICJwbGF5cmVhZHkiOiB7CiAgICAgICAgICAibWluX2RldmljZV9zZWN1cml0eV9sZXZlbCI6IDE1MCwKICAgICAgICAgICJwbGF5X2VuYWJsZXJzIjogWwogICAgICAgICAgICAiNzg2NjI3RDgtQzJBNi00NEJFLThGODgtMDhBRTI1NUIwMUE3IgogICAgICAgICAgXQogICAgICAgIH0KICAgICAgfQogICAgXQogIH0KfQ.l8PnZznspJ6lnNmfAE9UQV532Ypzt1JXQkvrk8gFSRw" + }, + } as TizenSourceParams; + + break; // Нативный FP (Safari & iOS) case VokaContentType.FAIRPLAY: if (drm != null && drm.type == DRMType.FAIRPLAY) { @@ -335,14 +354,20 @@ namespace VokaCorePlayer { certificateUrl: drm.certificateUrl, licenseUrl: drm.licenseUrl, }, - } + } as IVokaSource } break case VokaContentType.AES: playableContent = { sourceType: "application/vnd.apple.mpegurl", - } + } as IVokaSource break + case VokaContentType.MP4: + playableContent = { + sourceType: "video/mp4", + } as IVokaSource + break + } if (playableContent != null) { @@ -410,7 +435,7 @@ namespace VokaCorePlayer { // Create main container for player. const playerContainer = Dom.createEl( - 'object', + 'div', { id: `${DivID}` }, {} ) diff --git a/src/internal/player/native/VokaSourceHandler.ts b/src/internal/player/native/VokaSourceHandler.ts index 68660f1..b18383d 100644 --- a/src/internal/player/native/VokaSourceHandler.ts +++ b/src/internal/player/native/VokaSourceHandler.ts @@ -23,6 +23,8 @@ interface WebOSSourceProtection { interface TizenSourceProtection { type: string licenseServer: string + // ex: "X-AxDRM-Message:" + DRMToken + httpHeader: string } interface TizenSourceParams { protection: TizenSourceProtection | null @@ -41,8 +43,9 @@ interface IVokaSource { sourceType: string src: string startSeconds: number | null - // Dash WideVine only + // dash.js DRM options (widevine, playready only) keySystemOptions: [{ [key: string]: any }] | null + // FirePlay для Apple native protection: AppleSourceProtection | null webOSProtection: WebOSSourceProtection | null tizenParams: TizenSourceParams | null diff --git a/src/internal/player/native/tizen/tech/AVPlayHelper.ts b/src/internal/player/native/tizen/tech/AVPlayHelper.ts index 5bac0bc..099206c 100755 --- a/src/internal/player/native/tizen/tech/AVPlayHelper.ts +++ b/src/internal/player/native/tizen/tech/AVPlayHelper.ts @@ -25,6 +25,8 @@ namespace AVPlayHelper { } export interface IAVPlayer { + get lastError(): any + get avState(): State get state(): State get eventsEmitter(): EventBus get currentTime(): number @@ -61,6 +63,7 @@ namespace AVPlayHelper { class AVPlayer implements IAVPlayer { private readonly avPlayer: any + private _lastError: any private _state: State private _bus: EventBus private _currentTime: number @@ -74,51 +77,64 @@ namespace AVPlayHelper { this._currentTime = 0 this.isPrebufferPlaying = false - console.log("✨ avplay initialized " + this.avPlayer.getVersion()) + console.log("AVplay initialized " + this.avPlayer.getVersion()) } private addListener(avPlayer: any) { + if (AVPlayer.isAllowedState(this.state, State.idle) == null) { return } avPlayer.setListener({ oncurrentplaytime: (currentTime) => { + console.log("[AVPlayHelper] oncurrentplaytime : ", currentTime) this._currentTime = currentTime this._bus.publish( Events.time({time: this.currentTime, player: this}) ) }, - onevent: (eventType, eventData) => { console.log("event type: " + eventType + ", data: " + eventData) }, + onevent: (eventType, eventData) => { + console.log("[AVPlayHelper] event type: " + eventType + ", data: " + eventData) + }, onbufferingstart: () => { - // console.log("Buffering start.") + console.log("[AVPlayHelper] Buffering start.") this.isPrebufferPlaying = this.state == State.playing }, - onbufferingprogress: (percent) => { console.log("Buffering progress data : " + percent) }, + onbufferingprogress: (percent) => { + console.log("[AVPlayHelper] Buffering progress data : " + percent) + }, onbufferingcomplete: () => { + this.switchState(State.ready) if (this.isPrebufferPlaying) { this.isPrebufferPlaying = false this.avPlayer.play() } - console.log("Buffering complete.") + console.log("[AVPlayHelper] Buffering complete. avState, avPlayer ", this.avState, this.avPlayer) + }, + onrenderingstart: () => { + console.log('[AVPlayHelper] onRenderingStart'); + }, onstreamcompleted: () => { - console.log("Stream Completed") + console.log("[AVPlayHelper] Stream Completed") this.isPrebufferPlaying = false this.stop(false) }, onsubtitlechange: (duration, text, data3, data4) => { - console.log("subtitleText: " + text) + console.log("[AVPlayHelper] subtitleText: " + text) }, onerror: (eventType) => { - console.log("event type error : " + eventType) + this._lastError = eventType + console.log("[AVPlayHelper] event type error : " + eventType) }, ondrmevent: (drmEvent, drmData) => { - console.log("DRM callback: " + drmEvent + ", data: " + drmData) + console.log("[AVPlayHelper] DRM callback: ", drmEvent, drmData) }, + onerrormsg: (err, msg) => console.error("[AVPlayHelper] onerrormsg:", err, msg), }) } private switchState(state: State) { const arrived = AVPlayer.isAllowedState(this._state, state) if (arrived == null) { - console.log("Not allowed transition from " + this._state + " to " + state) + console.log("[AVPlayHelper] switchState Not allowed transition from " + this._state + " to " + state) return } @@ -126,6 +142,7 @@ namespace AVPlayHelper { this._bus.publish( Events.state({state: arrived, player: this}) ) + console.log("[AVPlayHelper] Transition from " + this._state + " to " + state) } // https://developer.samsung.com/media/2893/avplay_18082017fw.png @@ -147,13 +164,13 @@ namespace AVPlayHelper { if ([State.playing, State.paused].includes(arrive)) return arrive break } - console.log("🌚 " + depart + " -> " + arrive) + console.log("[AVPlayHelper] isAllowedState Not allowed state transition: " + depart + " -> " + arrive) return null } private requiredState(state: State): boolean { if (this.state != state) { - console.error("🐣 Incorrect state: " + this.state) + console.error("[AVPlayHelper] requiredState incorrect state: ", this.state, state) return false } return true @@ -161,7 +178,7 @@ namespace AVPlayHelper { private requireAllowedStates(states: State[]): boolean { if (!states.includes(this.state)) { - console.error("🐣 Incorrect state: " + this.state) + console.error("[AVPlayHelper] requireAllowedStates incorrect state: ", this.state, states, ) return false } return true @@ -169,7 +186,17 @@ namespace AVPlayHelper { // MARK: - IAVPlay - get state(): State { return this._state } + get lastError(): any { return this._lastError } + + get avState(): State { + console.log("[AVPlayHelper] avState: ", this.avPlayer.getState()) + return this.avPlayer.getState() + } + + get state(): State { + // console.log("[AVPlayHelper] state: _state, avState ", this._state, this.avState) + return this._state + } get eventsEmitter(): EventBus { return this._bus } get currentTime(): number { return this._currentTime / 1000 } @@ -179,14 +206,17 @@ namespace AVPlayHelper { get isPlaying(): boolean { return this.state == State.playing } open(url: string) { - if (AVPlayer.isAllowedState(this.state, State.idle) == null) { return } + if (AVPlayer.isAllowedState(this.state, State.idle) == null) { + return + } + console.log('[AVPlayHelper] open', url) this.avPlayer.open(url) this.switchState(State.idle) - this.addListener(this.avPlayer) } prepare(): Promise { + console.log('[AVPlayHelper] prepare'); if (!this.requiredState(State.idle)) { return Promise.reject('incorrect state') } @@ -195,21 +225,30 @@ namespace AVPlayHelper { this.avPlayer.prepareAsync( () => { this.switchState(State.ready) + console.log('[AVPlayHelper] prepareAsync completed: _state, avState', this._state, this.avState); resolve() }, - (error) => { reject('prepareAsync failed: ' + error) } + (error) => { + console.log('[AVPlayHelper] prepareFailed: ', error, this.avState); + console.log('[AVPlayHelper] prepareFailed stack: ', error.stack); + reject('prepare failed: ' + error) + } ) } ) } play() { - if (AVPlayer.isAllowedState(this.state, State.playing) == null) { return } + console.log('[AVPlayHelper] play'); + if (AVPlayer.isAllowedState(this.state, State.playing) == null) { + console.log('[AVPlayHelper] play invalid transition', this.state, State.playing); + return + } try { this.avPlayer.play() this.switchState(State.playing) } catch (error) { - console.error(error) + console.error("[AVPlayHelper] play error: ", error) } } @@ -219,7 +258,7 @@ namespace AVPlayHelper { this.avPlayer.pause() this.switchState(State.paused) } catch (error) { - console.error(error) + console.error("[AVPlayHelper] pause error: ",error) } } @@ -228,7 +267,7 @@ namespace AVPlayHelper { try { this.avPlayer.seekTo(seconds * 1000) } catch (e) { - console.log(e) + console.error("[AVPlayHelper] seekTo error: ", e) } } @@ -248,16 +287,22 @@ namespace AVPlayHelper { drmOptions(properties: any) { if (!this.requiredState(State.idle)) { return } - this.avPlayer.setDrm( - 'PLAYREADY', - 'SetProperties', - JSON.stringify(properties) - ) + console.log("[drmOptions] setDrm properties:", properties) + try { + this.avPlayer.setDrm( + 'PLAYREADY', + 'SetProperties', + JSON.stringify(properties) + ) + } catch (e) { + console.log("[drmOptions] setDrm error", e) + } } - setDisplayRect(x: number, y: number, width: number, heigth: number) { + setDisplayRect(x: number, y: number, width: number, height: number) { if (!this.requiredState(State.idle)) { return } - this.avPlayer.setDisplayRect(0, 0, 1920, 1080) + console.log('[AVPlayHelper] setDisplayRect', x, y, width, height); + this.avPlayer.setDisplayRect(x, y, width, height) } setDisplayMethod(method: string) { diff --git a/src/internal/player/native/tizen/tech/VokaTizenTech.ts b/src/internal/player/native/tizen/tech/VokaTizenTech.ts index ff13fc7..fa85033 100755 --- a/src/internal/player/native/tizen/tech/VokaTizenTech.ts +++ b/src/internal/player/native/tizen/tech/VokaTizenTech.ts @@ -1,3 +1,4 @@ +import { DeviceInfo, Stream } from "@/internal/player/native/tizen/models/PlayerLoadParameters"; import videojs from 'video.js' import VokaTizenSourceHandler from '../sourcehandler/VokaTizenSourceHandler' import AVPlayHelper from './AVPlayHelper' @@ -24,7 +25,7 @@ class VokaTizenTech extends Tech { private startTime: number | null private switchToThisTime: number | null - constructor(player, options, ready) { + constructor(options, ready) { const opt = options || {} opt.techId = VokaTizenTech.TECH_NAME super(opt, ready) @@ -48,6 +49,10 @@ class VokaTizenTech extends Tech { this.attachListeners(this.avPlayer) + if (options.source) { + this.setSource(options.source); + } + this.triggerReady() // from Component } @@ -76,6 +81,10 @@ class VokaTizenTech extends Tech { case AVPlayHelper.State.paused: this.trigger('pause') break + case AVPlayHelper.State.ready: + this.trigger('durationchange'); + this.trigger('canplay') + break } } ) @@ -88,9 +97,10 @@ class VokaTizenTech extends Tech { const el = document.createElement(this.elementTagName) el.id = playerId el.setAttribute('type', 'application/avplayer') - el.setAttribute('id', 'av-player') - el.style.width = '100%' - el.style.height = '100%' + el.setAttribute('className', 'vjs-tech tizen-avplay-tech') + el.style.width = '100vw' + el.style.height = '100vh' + this.el_ = el return el } @@ -115,7 +125,6 @@ class VokaTizenTech extends Tech { reset() { this.screenSaver.enable() - this.startTime = null this.selectedAudioTrack = null this.params = null @@ -136,8 +145,8 @@ class VokaTizenTech extends Tech { loop() { return false } setLoop(value) { } - seeking() { return false } - seekable() { return false } + seeking() { return true } + seekable() { return true } preload() { } setPreload(preload) { } @@ -149,13 +158,20 @@ class VokaTizenTech extends Tech { const src = typeof source.src === 'undefined' ? '' : source.src const sourceType = typeof source.sourceType === 'undefined' ? '' : source.sourceType let parameters = source.tizenParams + console.log("[VokaTizenTech.setSrc] source ", source) if (parameters == null) { - parameters = {} as TizenSourceParams + parameters = {} as TizenSourceParams + } + if (typeof parameters.isUHDSupported !== "boolean") { parameters.isUHDSupported = true - parameters.platform = {} + } + if (!parameters.platform) { + parameters.platform = {} as DeviceInfo + } + if (!parameters?.stream) { parameters.stream = { - url: src, - } + url: src + } as Stream } this.is4KSupported = parameters.isUHDSupported @@ -170,7 +186,7 @@ class VokaTizenTech extends Tech { if (!this.is4KSupported) { if (supportedBandWidthCount === 0) { - //onError(event, PlayerAccessError.CannotPlayStream); + console.log("[VokaTizenTech] No supported BandWidth", playListsAttributes) return } } @@ -183,20 +199,12 @@ class VokaTizenTech extends Tech { .split('.')[0], 10) const playerUrl = parameters.stream.url - // if (getProtocolByStreamURL(playerUrl) === Protocol.HLS) { - // playerUrl += '|COMPONENT=HLS'; - // } const protection = parameters.protection const hasDRM = protection != null && protection.type == 'playready' + console.log("[VokaTizenTech] setSrc: protection, hasDRM", protection, hasDRM) this.avPlayer.open(playerUrl) - // if (seekTo !== undefined && !isNaN(seekTo)) { - // webapis.avplay.seekTo(seekTo * 1000); - // - // switchToThisTime = null; - // } - /* https://developer.samsung.com/smarttv/develop/guides/multimedia/media-playback/using-avplay.html#drm-contents-playback-sequence */ @@ -205,10 +213,19 @@ class VokaTizenTech extends Tech { DeleteLicenseAfterUse: true, LicenseServer: protection.licenseServer, } + if (protection.httpHeader) { + properties.HttpHeader = protection.httpHeader + } this.avPlayer.drmOptions(properties) } - this.avPlayer.setDisplayRect(0, 0, 1920, 1080) + const rect = this.el_.getBoundingClientRect() + this.avPlayer.setDisplayRect( + Math.round(rect.left), + Math.round(rect.top), + Math.round(rect.width), + Math.round(rect.height) + ) this.avPlayer.setDisplayMethod('PLAYER_DISPLAY_MODE_AUTO_ASPECT_RATIO') if (this.is4KSupported) { @@ -277,7 +294,7 @@ class VokaTizenTech extends Tech { this.avPlayer.seekTo(this.switchToThisTime) this.switchToThisTime = null } else if (parameters.percentsWatched) { - this.avPlayer.seekTo(parameters.percentsWatched * this.getDuration() || 0) + this.avPlayer.seekTo(parameters.percentsWatched * this.duration() || 0) } }) } @@ -286,18 +303,25 @@ class VokaTizenTech extends Tech { } duration() { + console.log("[VokaTizenTech] duration() started") const parameters = this.params - if (parameters == null) { return } + if (parameters == null) { + console.log("[VokaTizenTech] duration is null") + return + } try { if (parameters.isLiveStream) { const [start, end] = this.avPlayer.getStreamingProperty('GET_LIVE_DURATION').split('|') const duration = this.avPlayer.duration + console.log("[VokaTizenTech] duration(): start, end", start, end) return ( duration > 0 ? duration : parseInt(end, 10) - parseInt(start, 10) || 0 ) } + console.log("[VokaTizenTech] duration ", this.avPlayer.duration) return this.avPlayer.duration } catch (e) { + console.error("[VokaTizenTech] Cant get duration", e) return 0 } } diff --git a/src/internal/player/native/webos/sourcehandler/VokaWebOSSourceHandler.ts b/src/internal/player/native/webos/sourcehandler/VokaWebOSSourceHandler.ts index b8f7be6..29109fc 100644 --- a/src/internal/player/native/webos/sourcehandler/VokaWebOSSourceHandler.ts +++ b/src/internal/player/native/webos/sourcehandler/VokaWebOSSourceHandler.ts @@ -93,7 +93,10 @@ export default class VokaWebOSSourceHandler extends VokaSourceHandler { private createDRMPlayer(source: IVokaSource, tech: VokaWebOSTech): WebOSPlayerNativeDRM { const protection = source.webOSProtection - if (protection == null) { return } + if (protection == null) { + console.log('[createDRMPlayer] cant get source.webOSProtection: source', source) + return + } const config = { licenseServer: protection.licenseServer, diff --git a/src/internal/player/native/webos/tech/VokaWebOSTech.ts b/src/internal/player/native/webos/tech/VokaWebOSTech.ts index 72a6ae5..bfc7bb4 100755 --- a/src/internal/player/native/webos/tech/VokaWebOSTech.ts +++ b/src/internal/player/native/webos/tech/VokaWebOSTech.ts @@ -13,7 +13,7 @@ class VokaWebOSTech extends Tech { private lastCurrentTime: number | null private playPromise: null - constructor(player, options, ready) { + constructor(options, ready) { const opt = options || {} opt.techId = VokaWebOSTech.TECH_NAME super(opt, ready) @@ -21,6 +21,10 @@ class VokaWebOSTech extends Tech { this.playPromise = null this.lastCurrentTime = null + if (options.source) { + this.setSource(options.source); + } + this.triggerReady() } @@ -122,10 +126,10 @@ class VokaWebOSTech extends Tech { setLoop(value) { } seeking() { - return false + return true } seekable() { - return false + return true } preload() { } @@ -157,7 +161,7 @@ class VokaWebOSTech extends Tech { currentSrc() { return '' } duration() { - return this.el().duration || 0 + return this.el().duration || 0 } setCurrentTime(seconds) { @@ -205,7 +209,7 @@ class VokaWebOSTech extends Tech { } paused() { - return false + return this.el().paused } ended() { diff --git a/src/plugins/VokaMagicRemotePlugin.ts b/src/plugins/VokaMagicRemotePlugin.ts index dfe390d..51891a7 100644 --- a/src/plugins/VokaMagicRemotePlugin.ts +++ b/src/plugins/VokaMagicRemotePlugin.ts @@ -18,7 +18,10 @@ namespace VokaMagicRemotePlugin { PAUSE: 19, NEXT: 417, - PREV: 412 + PREV: 412, + + TRACK_NEXT: 10233, + TRACK_PREV: 10232 } export class Plugin extends VideoPlugin { @@ -53,10 +56,12 @@ namespace VokaMagicRemotePlugin { break case KEY_CODES.LEFT: case KEY_CODES.PREV: + case KEY_CODES.TRACK_PREV: this.operationStepBackward() break case KEY_CODES.RIGHT: case KEY_CODES.NEXT: + case KEY_CODES.TRACK_NEXT: this.operationStepForward() break } @@ -104,13 +109,18 @@ namespace VokaMagicRemotePlugin { } private operationStepForward() { - const skipTime = 5//this.options.skip?.forward + console.log("[operationStepForward] started") + const skipTime = 5 //this.options.skip?.forward if (isNaN(this.player.duration()) || !skipTime) { return } const currentVideoTime = this.player.currentTime() + + console.log("[operationStepForward] currentTime = ", currentVideoTime) + const liveTracker = this.player.liveTracker + console.log("[operationStepForward] liveTracker, duration", liveTracker.isLive(), liveTracker.seekableEnd(), this.player.duration()) const duration = liveTracker && liveTracker.isLive() ? liveTracker.seekableEnd() @@ -123,6 +133,7 @@ namespace VokaMagicRemotePlugin { newTime = duration } + console.log("[operationStepForward] newTime = ", newTime) this.player.currentTime(newTime) } } diff --git a/src/public/VokaPlayerImpl.ts b/src/public/VokaPlayerImpl.ts index ef6c125..1a836fd 100644 --- a/src/public/VokaPlayerImpl.ts +++ b/src/public/VokaPlayerImpl.ts @@ -173,7 +173,10 @@ export class VokaPlayerImpl implements IVokaPlayer { // Логика для сайта voka - если нечего играть, плеер скрываем; player.load(iContent) .then(() => player.enable()) - .catch((error) => player.disable()) + .catch((error) => { + console.error("Error content loading, disable player", error) + player.disable() + }) } private async initialize(player: VokaCorePlayer.CorePlayer, features: SupportedCodecs.ISelectProtocolResult): Promise {