├── README.md ├── config └── 1.ini ├── default.aproj ├── dist └── demo.jpg ├── form └── about.aau ├── lib └── web │ └── layout │ └── behavior │ ├── about │ └── link.aau │ └── main │ ├── button.aau │ ├── channle.aau │ ├── player.aau │ └── playerControl.aau ├── main.aau ├── res ├── about.html ├── main.html └── styles │ ├── base.css │ ├── images │ ├── app.png │ ├── live.png │ ├── logo.jpg │ ├── open.png │ ├── pause.png │ ├── play.png │ ├── setting.png │ └── volume.png │ └── main.css └── tv.ico /README.md: -------------------------------------------------------------------------------- 1 | ## TV player 2 | A simple video player for http/ftp/mms/rtsp/rtmp/hls/m3u 3 | 4 | update: 5 | Jan,1 auto detect channel change 6 | Dec,20 add local file play support 7 | 8 | ## demo 9 | ![Demo](https://github.com/hikdo/tv/raw/master/dist/demo.jpg) 10 | -------------------------------------------------------------------------------- /config/1.ini: -------------------------------------------------------------------------------- 1 | test1,http://dlhls.cdn.zhanqi.tv/zqlive/36799_8JBTz.m3u8 2 | test2,http://dlhls.cdn.zhanqi.tv/zqlive/46455_xR2MZ.m3u8 3 | mp4,http://127.0.0.1/test.mp4 4 | wmv,http://127.0.0.1/test.wmv 5 | mov,http://127.0.0.1/test.mov 6 | flv,http://127.0.0.1/test.flv 7 | rmvb,http://127.0.0.1/test.rmvb 8 | rtmp,rtmp://127.0.0.1/test 9 | mms,mms://127.0.0.1/test 10 | rstp,rstp://127.0.0.1/test 11 | ftp,ftp://127.0.0.1/test.rmvb 12 | hflv,http://127.0.0.1/test.hflv 13 | mkv,http://127.0.0.1/test.mkv 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /default.aproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/default.aproj -------------------------------------------------------------------------------- /dist/demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/dist/demo.jpg -------------------------------------------------------------------------------- /form/about.aau: -------------------------------------------------------------------------------- 1 | /* 2 | * tv 3 | * https://github.com/hikdo 4 | * January 1,2017 5 | */ 6 | 7 | import win.ui; 8 | /*DSG{{*/ 9 | var winform = ..win.form(text="TV";right=408;bottom=187;border="none") 10 | winform.add() 11 | /*}}*/ 12 | 13 | import web.layout; 14 | import web.layout.behavior.windowCommand; 15 | import web.layout.behavior.windowSizer; 16 | import web.layout.behavior.about.link; 17 | 18 | var wbLayout = web.layout( winform ) 19 | wbLayout.go("/res/about.html") ; 20 | import win.ui.shadow; 21 | win.ui.shadow(winform); 22 | winform.show() 23 | win.loopMessage(); 24 | return winform; 25 | -------------------------------------------------------------------------------- /lib/web/layout/behavior/about/link.aau: -------------------------------------------------------------------------------- 1 | /* 2 | * tv 3 | * https://github.com/hikdo 4 | * January 1,2017 5 | */ 6 | namespace web.layout.behavior.about.link { 7 | 8 | onMouseClick = function( ltTarget,ltOwner,x,y,ltMouseParams ) { 9 | 10 | var link = ltOwner.getCustomAttribute("link"); 11 | if(link) { 12 | import process; 13 | process.execute(link); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/web/layout/behavior/main/button.aau: -------------------------------------------------------------------------------- 1 | /* 2 | * tv 3 | * https://github.com/hikdo 4 | * January 1,2017 5 | */ 6 | namespace web.layout.behavior.main.button{ 7 | 8 | onMouseClick = { 9 | 10 | aboutBtn = function( ltTarget,ltOwner,x,y,ltMouseParams ) { 11 | var aboutForm = ..mainForm.loadForm("/form/about.aau"); 12 | aboutForm.doModal(..mainForm.hwnd); 13 | } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /lib/web/layout/behavior/main/channle.aau: -------------------------------------------------------------------------------- 1 | /* 2 | * tv 3 | * https://github.com/hikdo 4 | * January 1,2017 5 | */ 6 | namespace web.layout.behavior.main.channle{ 7 | 8 | var curChannel = null; 9 | 10 | onMouseClick = function( ltTarget,ltOwner,x,y,ltMouseParams ) { 11 | 12 | if(ltMouseParams.button_state == 1/*_HL_MAIN_MOUSE_BUTTON*/) { 13 | var link = ltOwner.getCustomAttribute("link"); 14 | if(link) { 15 | if(..web.layout.behavior.main.player.aPlayer.getConfig(4) != link) { 16 | if(curChannel != null) { 17 | curChannel.setAttribute("selected",""); 18 | } 19 | curChannel = ltOwner; 20 | ltOwner.setAttribute("selected","selected"); 21 | ..web.layout.behavior.main.player.aPlayer.close(); 22 | ..web.layout.behavior.main.player.aPlayer.open(link); 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/web/layout/behavior/main/player.aau: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/lib/web/layout/behavior/main/player.aau -------------------------------------------------------------------------------- /lib/web/layout/behavior/main/playerControl.aau: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/lib/web/layout/behavior/main/playerControl.aau -------------------------------------------------------------------------------- /main.aau: -------------------------------------------------------------------------------- 1 | /* 2 | * tv 3 | * https://github.com/hikdo 4 | * January 1,2017 5 | */ 6 | 7 | import win.ui; 8 | /*DSG{{*/ 9 | mainForm = ..win.form(text="TV - live player";right=968;bottom=590;border="none") 10 | mainForm.add() 11 | /*}}*/ 12 | 13 | import web.layout; 14 | import web.layout.behavior.windowCommand; 15 | import web.layout.behavior.main.player; 16 | import web.layout.behavior.main.channle; 17 | import web.layout.behavior.main.button; 18 | import web.layout.behavior.main.playerControl; 19 | 20 | wbLayout = web.layout( mainForm ); 21 | 22 | if( _STUDIO_INVOKED ){ 23 | import web.layout.debug; 24 | wbLayout.attachEventHandler( web.layout.debug ); 25 | } 26 | 27 | import thread.event; 28 | import thread.command; 29 | import fsys.dirWatcher; 30 | 31 | thread.command.instance().updateChannel = function(){ 32 | ..web.layout.behavior.main.player.init(); 33 | } 34 | 35 | mainForm.watchThread = fsys.dirWatcher.thread( 36 | function(filename,action,actionText){ 37 | import thread.command; 38 | thread.command.updateChannel(); 39 | },"/config"); 40 | 41 | mainForm.onClose = function(hwnd,message,wParam,lParam){ 42 | if (!mainForm.watchThread) { 43 | return; 44 | } 45 | mainForm.watchThread.close(); 46 | } 47 | 48 | wbLayout.go("/res/main.html"); 49 | 50 | import win.ui.shadow; 51 | win.ui.shadow(mainForm); 52 | 53 | mainForm.show() 54 | return win.loopMessage(); 55 | -------------------------------------------------------------------------------- /res/about.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 11 | 12 | 18 |
19 |
20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 | -------------------------------------------------------------------------------- /res/main.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
00:00:00 / 00:00:00
34 | 35 |
36 |
37 |
38 | 39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /res/styles/base.css: -------------------------------------------------------------------------------- 1 | html,body{ 2 | margin:0; 3 | height:100%; 4 | background:#fff; 5 | overflow:hidden; 6 | } 7 | body[maximize]{ 8 | border-radius:0; 9 | } 10 | body[maximize] #header{ 11 | border-radius:0; 12 | } 13 | #header{ 14 | height:30px; 15 | line-height:30px; 16 | background:rgb(123, 138, 148); 17 | cursor:default; 18 | behavior:windowCommand; 19 | overflow:hidden; 20 | } 21 | #header .title-bar{ 22 | margin-right:95px; 23 | padding-left:5px; 24 | height:30px; 25 | font:system; 26 | color:#fff; 27 | } 28 | #header .title-bar .title { 29 | float:left; 30 | margin-left:8px; 31 | display:inline-block; 32 | } 33 | #header .titlebox{ 34 | width:max-intrinsic; 35 | height:30px; 36 | float:right; 37 | margin:0; 38 | overflow-x:hidden; 39 | } 40 | #header .titlebox a{ 41 | display:inline-block; 42 | width:max-intrinsic; 43 | height:30px; 44 | font-family:"Marlett"; 45 | font-size:14px; 46 | padding:0px 4px; 47 | color:#fff; 48 | cursor:default; 49 | } 50 | #header .titlebox a[command]:hover{ 51 | background:#6ebccf; 52 | } 53 | #header a[command="window-restore"]{ 54 | content:"2"; 55 | } 56 | #header i.logo { 57 | float:left; 58 | display:inline-block; 59 | margin-top:4px; 60 | width:24px; 61 | height:24px; 62 | background:url(images/app.png); 63 | } 64 | #container{ 65 | width:100%; 66 | height:100%%; 67 | flow: horizontal; 68 | margin:0 auto; 69 | overflow:hidden; 70 | } -------------------------------------------------------------------------------- /res/styles/images/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/app.png -------------------------------------------------------------------------------- /res/styles/images/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/live.png -------------------------------------------------------------------------------- /res/styles/images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/logo.jpg -------------------------------------------------------------------------------- /res/styles/images/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/open.png -------------------------------------------------------------------------------- /res/styles/images/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/pause.png -------------------------------------------------------------------------------- /res/styles/images/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/play.png -------------------------------------------------------------------------------- /res/styles/images/setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/setting.png -------------------------------------------------------------------------------- /res/styles/images/volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/res/styles/images/volume.png -------------------------------------------------------------------------------- /res/styles/main.css: -------------------------------------------------------------------------------- 1 | @set tv_scrollbar { 2 | .base { width: 2px; } 3 | :root { background-color: #0E0E0E; } 4 | :root:hover { } 5 | .base, .prev, .next, .next-page, .prev-page { 6 | background-color: transparent; border: none; 7 | } 8 | .slider { 9 | height:15px; 10 | background: #000; 11 | } 12 | .slider:hover { 13 | /*background: #333;*/ 14 | } 15 | } 16 | #aboutBtn { 17 | behavior:~ "main.button"; 18 | } 19 | #channleList { 20 | width:200px; 21 | height:100%%; 22 | background:#0E0E0E; 23 | overflow:auto; vertical-scrollbar: tv_scrollbar; 24 | padding:15px 0; 25 | } 26 | #channleList:hover { 27 | assigned!: self:focus = true; 28 | } 29 | #player {height:100%%;background:#000000;padding:5px;} 30 | #playerWidget { background:#000000;} 31 | #channelListUl {margin:0;padding:0;} 32 | #channelListUl li { 33 | list-style:none; 34 | display:block; 35 | width:100%%; 36 | height:30px; 37 | line-height:30px; 38 | color:#FFF; 39 | font-size:12px; 40 | cursor:pointer; 41 | padding-left:10px; 42 | behavior:~url(main.channle); 43 | } 44 | #channelListUl li a { 45 | display:block; 46 | width:100%%; 47 | cursor:pointer; 48 | padding-left:23px; 49 | foreground:url(/res/styles/images/live.png) no-repeat left center; 50 | } 51 | #channelListUl li:hover { 52 | color:#B70031; 53 | background:#000000; 54 | opacity:0.9; 55 | } 56 | #channelListUl li[selected=selected]{ 57 | color:#B70031; 58 | background:#000000; 59 | opacity:0.9; 60 | } 61 | #controls { 62 | height:30px; 63 | width:100%%; 64 | background: #333; 65 | display:table; 66 | padding:0px 15px; 67 | } 68 | #ctrl-wrap { 69 | width:100%%;height:100%%; 70 | display:table-cell;vertical-align:middle; 71 | flow:horizontal; 72 | } 73 | #ctrl-left,#ctrl-right { 74 | flow:horizontal; 75 | width:120px; 76 | } 77 | #ctrl-left {text-align:left;} 78 | #ctrl-center { 79 | width:100%%; 80 | flow:horizontal; 81 | padding:0 30px 0 10px; 82 | } 83 | .ctrl-btn {height: 16px; width:16px;margin-right:25px; cursor:pointer; overflow: hidden; behavior:~url(main.playerControl);} 84 | #ctrlChannel {background: url(/res/styles/images/setting.png);} 85 | #ctrlOpen {background: url(/res/styles/images/open.png);} 86 | #ctrlPlay {background: url(/res/styles/images/play.png);} 87 | #ctrlMute {width:19px; height: 23px; background: url(/res/styles/images/volume.png); behavior:~url(main.playerControl);} 88 | #ctrlVolume {margin-top:5px;behavior:~url(main.playerControl);} 89 | #ctrlVolume img {display: none; width:7px; height:11px; overflow:hidden;} 90 | #ctrlVolume img {display: block; background-image: none;background-color: #f26c4f; foreground-image: none; } 91 | #ctrlProgress {margin-top:8px;width:100%%;behavior:~url(main.playerControl);} 92 | #ctrlProgress img {width:7px; height:11px;display: block; background-image: none;background-color: #f26c4f; foreground-image: none; } 93 | #timeshow {width:150px;line-height: 30px;color:#FFF;font-size:12px;} -------------------------------------------------------------------------------- /tv.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yikza/tv/5e209d0e33072ad080f1110a39453b9482f10a85/tv.ico --------------------------------------------------------------------------------