controller.dart 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. part of './ijkplayer.dart';
  2. /// Media Controller
  3. class IjkMediaController {
  4. /// MediaController
  5. IjkMediaController({
  6. this.autoRotate = true,
  7. });
  8. /// texture id from native
  9. int _textureId;
  10. /// It will automatically correct the direction of the video.
  11. bool autoRotate;
  12. /// texture id from native
  13. int get textureId => _textureId;
  14. /// set texture id, Normally the user does not call
  15. set textureId(int id) {
  16. _textureId = id;
  17. _textureIdController.add(id);
  18. }
  19. /// on texture id change
  20. StreamController<int> _textureIdController = StreamController.broadcast();
  21. /// on texture id change
  22. Stream<int> get textureIdStream => _textureIdController.stream;
  23. /// Channel of flutter and native.
  24. _IjkPlugin _plugin;
  25. /// Whether texture id is null
  26. bool get isInit => textureId == null;
  27. /// channel of native to flutter
  28. _IJKEventChannel eventChannel;
  29. /// playing state
  30. bool _isPlaying = false;
  31. /// playing state
  32. bool get isPlaying => _isPlaying == true;
  33. /// playing state
  34. set isPlaying(bool value) {
  35. this._isPlaying = value;
  36. _playingController.add(value);
  37. }
  38. /// playing state stream controller
  39. StreamController<bool> _playingController = StreamController.broadcast();
  40. /// playing state stream
  41. Stream<bool> get playingStream => _playingController.stream;
  42. /// video info stream controller
  43. StreamController<VideoInfo> _videoInfoController =
  44. StreamController.broadcast();
  45. /// video info stream
  46. Stream<VideoInfo> get videoInfoStream => _videoInfoController.stream;
  47. /// video volume stream controller
  48. StreamController<int> _volumeController = StreamController.broadcast();
  49. /// video volume stream
  50. Stream<int> get volumeStream => _volumeController.stream;
  51. /// video volume, not system volume
  52. int _volume = 100;
  53. /// video volume, not system volume
  54. set volume(int value) {
  55. if (value > 100) {
  56. value = 100;
  57. } else if (value < 0) {
  58. value = 0;
  59. }
  60. this._volume = value;
  61. _volumeController.add(value);
  62. _setVolume(value);
  63. }
  64. /// video volume, not system volume
  65. int get volume => _volume;
  66. /// create ijk texture id from native
  67. Future<void> _initIjk() async {
  68. try {
  69. var id = await _createIjk();
  70. this.textureId = id;
  71. _plugin = _IjkPlugin(id);
  72. eventChannel = _IJKEventChannel(this);
  73. await eventChannel.init();
  74. volume = 100;
  75. } catch (e) {
  76. LogUtils.log(e);
  77. LogUtils.log("初始化失败");
  78. }
  79. }
  80. /// [reset] and close all controller
  81. void dispose() async {
  82. await reset();
  83. _playingController.close();
  84. _videoInfoController.close();
  85. _textureIdController.close();
  86. _volumeController.close();
  87. }
  88. /// dispose all resource
  89. Future<void> reset() async {
  90. volume = 100;
  91. this.textureId = null;
  92. _plugin?.dispose();
  93. _plugin = null;
  94. eventChannel?.dispose();
  95. eventChannel = null;
  96. }
  97. /// set net DataSource
  98. Future<void> setNetworkDataSource(
  99. String url, {
  100. bool autoPlay = false,
  101. }) async {
  102. await _initDataSource(() async {
  103. await _plugin?.setNetworkDataSource(uri: url);
  104. }, autoPlay);
  105. }
  106. /// set asset DataSource
  107. Future<void> setAssetDataSource(
  108. String name, {
  109. String package,
  110. bool autoPlay = false,
  111. }) async {
  112. await _initDataSource(() async {
  113. await _plugin?.setAssetDataSource(name, package);
  114. }, autoPlay);
  115. }
  116. /// set file DataSource
  117. Future<void> setFileDataSource(
  118. File file, {
  119. bool autoPlay = false,
  120. }) async {
  121. await _initDataSource(() async {
  122. await _plugin?.setFileDataSource(file.absolute.path);
  123. }, autoPlay);
  124. }
  125. /// dispose last textureId resource
  126. Future<void> _initDataSource(
  127. Future setDataSource(),
  128. bool autoPlay,
  129. ) async {
  130. autoPlay ??= false;
  131. if (this.textureId != null) {
  132. await _plugin?.dispose();
  133. }
  134. await _initIjk();
  135. _autoPlay(autoPlay);
  136. await setDataSource();
  137. }
  138. /// Play or pause according to your current status
  139. Future<void> playOrPause() async {
  140. var videoInfo = await getVideoInfo();
  141. var playing = videoInfo.isPlaying;
  142. if (playing) {
  143. await _plugin?.pause();
  144. } else {
  145. await _plugin?.play();
  146. }
  147. refreshVideoInfo();
  148. }
  149. /// play media
  150. Future<void> play() async {
  151. await _plugin?.play();
  152. refreshVideoInfo();
  153. }
  154. /// pause media
  155. Future<void> pause() async {
  156. await _plugin?.pause();
  157. refreshVideoInfo();
  158. }
  159. /// seek to second
  160. ///
  161. /// [target] unit is second
  162. Future<void> seekTo(double target) async {
  163. await _plugin?.seekTo(target);
  164. refreshVideoInfo();
  165. }
  166. /// get video info from native
  167. Future<VideoInfo> getVideoInfo() async {
  168. Map<String, dynamic> result = await _plugin?.getInfo();
  169. var info = VideoInfo.fromMap(result);
  170. return info;
  171. }
  172. /// request info and notify
  173. Future<void> refreshVideoInfo() async {
  174. var info = await getVideoInfo();
  175. isPlaying = info.isPlaying;
  176. if (info.hasData) _videoInfoController?.add(info);
  177. LogUtils.log("info = $info");
  178. }
  179. /// AutoPlay use
  180. void _autoPlay(bool autoPlay) {
  181. if (autoPlay) {
  182. eventChannel?.autoPlay(this);
  183. }
  184. }
  185. /// set video volume
  186. Future<void> _setVolume(int volume) async {
  187. await _plugin?.setVolume(volume);
  188. }
  189. /// [pause] and [seekTo] 0
  190. Future<void> stop() async {
  191. // await _plugin?.stop();
  192. // refreshVideoInfo();
  193. await _plugin?.pause();
  194. await _plugin?.seekTo(0);
  195. refreshVideoInfo();
  196. }
  197. /// get system volume
  198. Future<int> getSystemVolume() async {
  199. return IjkManager.getSystemVolume();
  200. }
  201. /// set system volume
  202. Future<void> setSystemVolume(int volume) async {
  203. await IjkManager.setSystemVolume(volume);
  204. }
  205. }
  206. /// about channel
  207. MethodChannel _globalChannel = MethodChannel("top.kikt/ijkplayer");
  208. Future<int> _createIjk() async {
  209. int id = await _globalChannel.invokeMethod("create");
  210. return id;
  211. }
  212. class _IjkPlugin {
  213. MethodChannel get channel => MethodChannel("top.kikt/ijkplayer/$textureId");
  214. /// texture id
  215. int textureId;
  216. _IjkPlugin(this.textureId);
  217. Future<void> dispose() async {
  218. await _globalChannel.invokeMethod("dispose", {"id": textureId});
  219. }
  220. Future<void> play() async {
  221. await channel.invokeMethod("play");
  222. }
  223. Future<void> pause() async {
  224. await channel.invokeMethod("pause");
  225. }
  226. Future<void> stop() async {
  227. await channel.invokeMethod("stop");
  228. }
  229. Future<void> setNetworkDataSource({String uri}) async {
  230. LogUtils.log("id = $textureId net uri = $uri");
  231. await channel.invokeMethod("setNetworkDataSource", {"uri": uri});
  232. }
  233. Future<void> setAssetDataSource(String name, String package) async {
  234. LogUtils.log("id = $textureId asset name = $name package = $package");
  235. var params = <String, dynamic>{
  236. "name": name,
  237. };
  238. if (package != null) {
  239. params["package"] = package;
  240. }
  241. await channel.invokeMethod("setAssetDataSource", params);
  242. }
  243. Future<void> setFileDataSource(String path) async {
  244. if (!File(path).existsSync()) {
  245. return Error.fileNotExists;
  246. }
  247. await channel.invokeMethod("setFileDataSource", <String, dynamic>{
  248. "path": path,
  249. });
  250. LogUtils.log("id = $textureId file path = $path");
  251. }
  252. Future<Map<String, dynamic>> getInfo() async {
  253. var map = await channel.invokeMethod("getInfo");
  254. if (map == null) {
  255. return null;
  256. } else {
  257. return map.cast<String, dynamic>();
  258. }
  259. }
  260. Future<void> seekTo(double target) async {
  261. await channel.invokeMethod("seekTo", <String, dynamic>{
  262. "target": target,
  263. });
  264. }
  265. Future<void> setVolume(int volume) async {
  266. await channel.invokeMethod("setVolume", <String, dynamic>{
  267. "volume": volume,
  268. });
  269. }
  270. }