winlin

update the publisher, to auto prompt the dialog to get the publisher.

@@ -401,13 +401,18 @@ function SrsPublisher(container, width, height) { @@ -401,13 +401,18 @@ function SrsPublisher(container, width, height) {
401 this.code = 0; 401 this.code = 0;
402 402
403 // error code defines. 403 // error code defines.
404 - this.error_device_muted = 100; 404 + this.errors = {
  405 + "100": "无法获取指定的摄像头", //error_camera_get
  406 + "101": "无法获取指定的麦克风", //error_microphone_get
  407 + "102": "摄像头为禁用状态,推流时请允许flash访问摄像头", //error_camera_muted
  408 + };
405 } 409 }
406 /** 410 /**
407 * user can set some callback, then start the publisher. 411 * user can set some callback, then start the publisher.
408 * callbacks: 412 * callbacks:
409 * on_publisher_ready(cameras, microphones):int, when srs publisher ready, user can publish. 413 * on_publisher_ready(cameras, microphones):int, when srs publisher ready, user can publish.
410 -* on_publisher_error(code):int, when srs publisher error, callback this method. 414 +* on_publisher_error(code, desc):int, when srs publisher error, callback this method.
  415 +* on_publisher_warn(code, desc):int, when srs publisher warn, callback this method.
411 */ 416 */
412 SrsPublisher.prototype.start = function() { 417 SrsPublisher.prototype.start = function() {
413 // embed the flash. 418 // embed the flash.
@@ -415,6 +420,7 @@ SrsPublisher.prototype.start = function() { @@ -415,6 +420,7 @@ SrsPublisher.prototype.start = function() {
415 flashvars.id = this.id; 420 flashvars.id = this.id;
416 flashvars.on_publisher_ready = "__srs_on_publisher_ready"; 421 flashvars.on_publisher_ready = "__srs_on_publisher_ready";
417 flashvars.on_publisher_error = "__srs_on_publisher_error"; 422 flashvars.on_publisher_error = "__srs_on_publisher_error";
  423 + flashvars.on_publisher_warn = "__srs_on_publisher_warn";
418 424
419 var params = {}; 425 var params = {};
420 params.wmode = "opaque"; 426 params.wmode = "opaque";
@@ -464,9 +470,13 @@ SrsPublisher.prototype.on_publisher_ready = function(cameras, microphones) { @@ -464,9 +470,13 @@ SrsPublisher.prototype.on_publisher_ready = function(cameras, microphones) {
464 /** 470 /**
465 * when publisher error. 471 * when publisher error.
466 * @code the error code. 472 * @code the error code.
  473 +* @desc the error desc message.
467 */ 474 */
468 -SrsPublisher.prototype.on_publisher_error = function(code) {  
469 - throw new Error("publisher error. code=" + code); 475 +SrsPublisher.prototype.on_publisher_error = function(code, desc) {
  476 + throw new Error("publisher error. code=" + code + ", desc=" + desc);
  477 +}
  478 +SrsPublisher.prototype.on_publisher_warn = function(code, desc) {
  479 + throw new Error("publisher warn. code=" + code + ", desc=" + desc);
470 } 480 }
471 function __srs_find_publisher(id) { 481 function __srs_find_publisher(id) {
472 for (var i = 0; i < SrsPublisher.__publishers.length; i++) { 482 for (var i = 0; i < SrsPublisher.__publishers.length; i++) {
@@ -494,6 +504,13 @@ function __srs_on_publisher_error(id, code) { @@ -494,6 +504,13 @@ function __srs_on_publisher_error(id, code) {
494 504
495 publisher.code = code; 505 publisher.code = code;
496 506
497 - publisher.on_publisher_error(code); 507 + publisher.on_publisher_error(code, publisher.errors[""+code]);
  508 +}
  509 +function __srs_on_publisher_warn(id, code) {
  510 + var publisher = __srs_find_publisher(id);
  511 +
  512 + publisher.code = code;
  513 +
  514 + publisher.on_publisher_warn(code, publisher.errors[""+code]);
498 } 515 }
499 516
@@ -115,15 +115,17 @@ @@ -115,15 +115,17 @@
115 } 115 }
116 $("#sl_bitrate option[value='350']").attr("selected", true); 116 $("#sl_bitrate option[value='350']").attr("selected", true);
117 }; 117 };
118 - srs_publisher.on_publisher_error = function(code) {  
119 - if (code == srs_publisher.error_device_muted) {  
120 - error(code, "摄像头和麦克风被禁用,请右键flash播放器启用。");  
121 - } else {  
122 - error(code, "未知系统错误");  
123 - } 118 + srs_publisher.on_publisher_error = function(code, desc) {
  119 + error(code, desc);
  120 + };
  121 + srs_publisher.on_publisher_warn = function(code, desc) {
  122 + warn(code, desc);
124 }; 123 };
125 srs_publisher.start(); 124 srs_publisher.start();
126 125
  126 + // if no play specified, donot show the player, for debug the publisher.
  127 + var query = parse_query_string();
  128 + if (query.no_play != "true") {
127 // start the normal player with HLS supported. 129 // start the normal player with HLS supported.
128 remote_player = new SrsPlayer("remote_player", 430, 185); 130 remote_player = new SrsPlayer("remote_player", 430, 185);
129 remote_player.on_player_ready = function() { 131 remote_player.on_player_ready = function() {
@@ -139,6 +141,7 @@ @@ -139,6 +141,7 @@
139 realtime_player.set_fs("screen", 100); 141 realtime_player.set_fs("screen", 100);
140 }; 142 };
141 realtime_player.start(); 143 realtime_player.start();
  144 + }
142 }); 145 });
143 146
144 /** 147 /**
@@ -209,10 +212,13 @@ @@ -209,10 +212,13 @@
209 info("开始推流到服务器"); 212 info("开始推流到服务器");
210 srs_publisher.publish(url, vcodec, acodec); 213 srs_publisher.publish(url, vcodec, acodec);
211 214
  215 + if (realtime_player) {
212 // directly play the url for the realtime player. 216 // directly play the url for the realtime player.
213 realtime_player.stop(); 217 realtime_player.stop();
214 realtime_player.play(url); 218 realtime_player.play(url);
  219 + }
215 220
  221 + if (remote_player) {
216 // the normal player should play the transcoded stream in another vhost. 222 // the normal player should play the transcoded stream in another vhost.
217 // for example, publish stream to vhost players, 223 // for example, publish stream to vhost players,
218 // the realtime player play the vhost players, which may donot support HLS, 224 // the realtime player play the vhost players, which may donot support HLS,
@@ -223,14 +229,20 @@ @@ -223,14 +229,20 @@
223 remote_player.stop(); 229 remote_player.stop();
224 remote_player.play(pub_url); 230 remote_player.play(pub_url);
225 } 231 }
  232 + }
226 233
227 function info(desc) { 234 function info(desc) {
228 - $("#txt_log").removeClass("alert-error").addClass("alert-info"); 235 + $("#txt_log").addClass("alert-info").removeClass("alert-error").removeClass("alert-warn");
229 $("#txt_log_title").text("Info:"); 236 $("#txt_log_title").text("Info:");
230 $("#txt_log_msg").text(desc); 237 $("#txt_log_msg").text(desc);
231 } 238 }
  239 + function warn(code, desc) {
  240 + $("#txt_log").removeClass("alert-info").removeClass("alert-error").addClass("alert-warn");
  241 + $("#txt_log_title").text("Warn:");
  242 + $("#txt_log_msg").text("code: " + code + ", " + desc);
  243 + }
232 function error(code, desc) { 244 function error(code, desc) {
233 - $("#txt_log").removeClass("alert-info").addClass("alert-error"); 245 + $("#txt_log").removeClass("alert-info").addClass("alert-error").removeClass("alert-warn");
234 $("#txt_log_title").text("Error:"); 246 $("#txt_log_title").text("Error:");
235 $("#txt_log_msg").text("code: " + code + ", " + desc); 247 $("#txt_log_msg").text("code: " + code + ", " + desc);
236 } 248 }
@@ -258,7 +270,7 @@ @@ -258,7 +270,7 @@
258 <div class="alert alert-info fade in" id="txt_log"> 270 <div class="alert alert-info fade in" id="txt_log">
259 <button type="button" class="close" data-dismiss="alert">×</button> 271 <button type="button" class="close" data-dismiss="alert">×</button>
260 <strong><span id="txt_log_title">Usage:</span></strong> 272 <strong><span id="txt_log_title">Usage:</span></strong>
261 - <span id="txt_log_msg">允许Flash访问摄像头,设置编码参数,点“发布视频”即可推流</span> 273 + <span id="txt_log_msg">设置编码参数,点“发布视频”,允许Flash访问摄像头即可推流</span>
262 </div> 274 </div>
263 <div class="control-group"> 275 <div class="control-group">
264 <div class="form-inline"> 276 <div class="form-inline">
@@ -24,6 +24,7 @@ package @@ -24,6 +24,7 @@ package
24 // user set callback 24 // user set callback
25 private var js_on_publisher_ready:String = null; 25 private var js_on_publisher_ready:String = null;
26 private var js_on_publisher_error:String = null; 26 private var js_on_publisher_error:String = null;
  27 + private var js_on_publisher_warn:String = null;
27 28
28 // publish param url. 29 // publish param url.
29 private var user_url:String = null; 30 private var user_url:String = null;
@@ -41,7 +42,9 @@ package @@ -41,7 +42,9 @@ package
41 private var media_microphone:Microphone = null; 42 private var media_microphone:Microphone = null;
42 43
43 // error code. 44 // error code.
44 - private const error_device_muted:int = 100; 45 + private const error_camera_get:int = 100;
  46 + private const error_microphone_get:int = 101;
  47 + private const error_camera_muted:int = 102;
45 48
46 public function srs_publisher() 49 public function srs_publisher()
47 { 50 {
@@ -74,6 +77,7 @@ package @@ -74,6 +77,7 @@ package
74 this.js_id = flashvars.id; 77 this.js_id = flashvars.id;
75 this.js_on_publisher_ready = flashvars.on_publisher_ready; 78 this.js_on_publisher_ready = flashvars.on_publisher_ready;
76 this.js_on_publisher_error = flashvars.on_publisher_error; 79 this.js_on_publisher_error = flashvars.on_publisher_error;
  80 + this.js_on_publisher_warn = flashvars.on_publisher_warn;
77 81
78 flash.utils.setTimeout(this.system_on_js_ready, 0); 82 flash.utils.setTimeout(this.system_on_js_ready, 0);
79 } 83 }
@@ -106,6 +110,10 @@ package @@ -106,6 +110,10 @@ package
106 trace("system error, code=" + code + ", error=" + desc); 110 trace("system error, code=" + code + ", error=" + desc);
107 flash.external.ExternalInterface.call(this.js_on_publisher_error, this.js_id, code); 111 flash.external.ExternalInterface.call(this.js_on_publisher_error, this.js_id, code);
108 } 112 }
  113 + private function system_warn(code:int, desc:String):void {
  114 + trace("system warn, code=" + code + ", error=" + desc);
  115 + flash.external.ExternalInterface.call(this.js_on_publisher_warn, this.js_id, code);
  116 + }
109 117
110 /** 118 /**
111 * publish stream to server. 119 * publish stream to server.
@@ -129,27 +137,22 @@ package @@ -129,27 +137,22 @@ package
129 // microphone and camera 137 // microphone and camera
130 var m:Microphone = Microphone.getMicrophone(acodec.device_code); 138 var m:Microphone = Microphone.getMicrophone(acodec.device_code);
131 if(m == null){ 139 if(m == null){
132 - trace("failed to open microphone " + acodec.device_code + "(" + acodec.device_name + ")");  
133 - }  
134 - if(m.muted){  
135 - trace("Access Denied, microphone " + acodec.device_code + "(" + acodec.device_name + ") is muted");  
136 - m = null; 140 + this.system_error(this.error_microphone_get, "failed to open microphone " + acodec.device_code + "(" + acodec.device_name + ")");
  141 + return;
137 } 142 }
  143 + // ignore muted, for flash will require user to access it.
138 144
139 // Remark: the name is the index! 145 // Remark: the name is the index!
140 var c:Camera = Camera.getCamera(vcodec.device_code); 146 var c:Camera = Camera.getCamera(vcodec.device_code);
141 if(c == null){ 147 if(c == null){
142 - trace("failed to open camera " + vcodec.device_code + "(" + vcodec.device_name + ")");  
143 - }  
144 - if(c.muted){  
145 - trace("Access Denied, camera " + vcodec.device_code + "(" + vcodec.device_name + ") is muted");  
146 - c = null;  
147 - }  
148 -  
149 - if (m == null && c == null) {  
150 - system_error(error_device_muted, "failed to publish, for neither camera or microphone is ok."); 148 + this.system_error(this.error_camera_get, "failed to open camera " + vcodec.device_code + "(" + vcodec.device_name + ")");
151 return; 149 return;
152 } 150 }
  151 + // ignore muted, for flash will require user to access it.
  152 + // but we still warn user.
  153 + if(c && c.muted){
  154 + this.system_warn(this.error_camera_muted, "Access Denied, camera " + vcodec.device_code + "(" + vcodec.device_name + ") is muted");
  155 + }
153 156
154 this.media_camera = c; 157 this.media_camera = c;
155 this.media_microphone = m; 158 this.media_microphone = m;