• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import featureAbility from '@ohos.ability.featureAbility'
17import RemoteDeviceModel from '../../model/RemoteDeviceModel.js'
18import PlayerModel from '../../model/PlayerModel.js'
19import KvStoreModel from '../../model/KvStoreModel.js'
20import { logger } from '../../model/Logger'
21
22function getShownTimer(ms) {
23  var seconds = Math.floor(ms / 1000)
24  var sec = seconds % 60
25  var min = (seconds - sec) / 60
26  if (sec < 10) {
27    sec = '0' + sec
28  }
29  if (min < 10) {
30    min = '0' + min
31  }
32  return min + ':' + sec
33}
34
35const REMOTE_ABILITY_STARTED = 'remoteAbilityStarted'
36var DEVICE_LIST_LOCALHOST
37const TAG = 'Index'
38let lastTime = -1
39
40export default {
41  data: {
42    title: '',
43    currentTimeText: '',
44    totalTimeText: '',
45    totalMs: 0,
46    currentProgress: 0,
47    deviceList: [],
48    btnPlaySrc: '/common/media/ic_play.svg',
49    albumSrc: '/common/media/album.png',
50    remoteDeviceModel: new RemoteDeviceModel(),
51    playerModel: new PlayerModel(),
52    kvStoreModel: new KvStoreModel(),
53    isDialogShowing: false,
54    isSwitching: false,
55  },
56  onInit() {
57    logger.info(TAG, `onInit begin`)
58    this.grantPermission()
59    DEVICE_LIST_LOCALHOST = {
60      name: this.$t('strings.localhost'),
61      id: 'localhost',
62    }
63    this.deviceList = [DEVICE_LIST_LOCALHOST]
64
65    this.currentTimeText = getShownTimer(0)
66    this.playerModel.setOnStatusChangedListener((isPlaying) => {
67      logger.debug(TAG, `on player status changed, isPlaying=${isPlaying} refresh ui`)
68      this.playerModel.setOnPlayingProgressListener((currentTimeMs) => {
69        if (lastTime === currentTimeMs) {
70          this.playerModel.pause()
71        } else {
72          lastTime = currentTimeMs
73        }
74        this.currentTimeText = getShownTimer(currentTimeMs)
75        this.currentProgress = Math.floor(currentTimeMs / this.totalMs * 100)
76      })
77      if (isPlaying) {
78        this.btnPlaySrc = '/common/media/ic_pause.svg'
79      } else {
80        this.btnPlaySrc = '/common/media/ic_play.svg'
81      }
82    })
83    this.playerModel.getPlaylist(() => {
84      logger.info(TAG, `on playlist generated, refresh ui`)
85      this.restoreFromWant()
86    })
87    logger.info(TAG, `onInit end`)
88  },
89  grantPermission() {
90    logger.info(TAG, `grantPermission`)
91    let context = featureAbility.getContext()
92    context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) {
93      logger.debug(TAG, `grantPermission,requestPermissionsFromUser,result.requestCode=${result.requestCode}`)
94    })
95  },
96  restoreFromWant() {
97    featureAbility.getWant((error, want) => {
98      logger.debug(TAG, `featureAbility.getWant=${JSON.stringify(want)}`)
99      var status = want.parameters
100      if (status != null && status.uri != null) {
101        this.kvStoreModel.broadcastMessage(REMOTE_ABILITY_STARTED)
102        logger.info(TAG, `restorePlayingStatus`)
103        this.playerModel.restorePlayingStatus(status, (index) => {
104          logger.debug(TAG, `restorePlayingStatus finished, index=${index}`)
105          if (index >= 0) {
106            this.refreshSongInfo(index)
107          } else {
108            this.playerModel.preLoad(0, () => {
109              this.refreshSongInfo(0)
110            })
111          }
112        })
113      } else {
114        this.playerModel.preLoad(0, () => {
115          this.refreshSongInfo(0)
116        })
117      }
118    })
119  },
120  onNewRequest() {
121    logger.info(TAG, `onNewRequest`)
122  },
123  onHide() {
124    logger.info(TAG, `onHide isDialogShowing=${this.isDialogShowing}`)
125    if (this.isDialogShowing === true) {
126      this.dismissDialog()
127      return true
128    }
129    return false
130  },
131  onDestroy() {
132    logger.info(TAG, `onDestroy begin`)
133    if (this.playerModel === undefined) {
134      return
135    }
136    this.playerModel.release()
137    this.remoteDeviceModel.unregisterDeviceListCallback()
138    logger.info(TAG, `onDestroy end`)
139  },
140  refreshSongInfo(index) {
141    logger.debug(TAG, `refreshSongInfo ${index}/${this.playerModel.playlist.audioFiles.length}`)
142    if (index >= this.playerModel.playlist.audioFiles.length) {
143      logger.warn(TAG, `refreshSongInfo ignored`)
144      return
145    }
146    // update song title
147    this.title = this.playerModel.playlist.audioFiles[index].name
148    this.albumSrc = (index % 2 === 0) ? '/common/media/album.png' : '/common/media/album2.png'
149
150    // update duration
151    this.totalMs = this.playerModel.getDuration()
152    this.totalTimeText = getShownTimer(this.totalMs)
153    this.currentTimeText = getShownTimer(0)
154    this.currentProgress = 0
155
156    logger.debug(TAG, `refreshSongInfo this.title=${this.title} this.totalMs=${this.totalMs}`
157    + ` this.totalTimeText=${this.totalTimeText}this.currentTimeText=${this.currentTimeText}`)
158  },
159  setProgress(e) {
160    logger.debug(TAG, `setProgress ${e.mode}, ${e.value}`)
161    this.currentProgress = e.value
162    if (isNaN(this.totalMs)) {
163      this.currentProgress = 0
164      logger.debug(TAG, `setProgress ignored, totalMs=${this.totalMs}`)
165      return
166    }
167    var currentMs = this.currentProgress / 100 * this.totalMs
168    this.currentTimeText = getShownTimer(currentMs)
169    if (e.mode === 'end' || e.mode === 'click') {
170      logger.debug(TAG, `player.seek ${currentMs}`)
171      this.playerModel.seek(currentMs)
172    }
173  },
174  onPreviousClick() {
175    if (this.isSwitching) {
176      logger.info(TAG, `onPreviousClick ignored, isSwitching`)
177      return
178    }
179    logger.info(TAG, `onPreviousClick`)
180    this.playerModel.index--
181    if (this.playerModel.index < 0 && this.playerModel.playlist.audioFiles.length >= 1) {
182      this.playerModel.index = this.playerModel.playlist.audioFiles.length - 1
183    }
184    this.currentProgress = 0
185    this.isSwitching = true
186    this.playerModel.preLoad(this.playerModel.index, () => {
187      this.refreshSongInfo(this.playerModel.index)
188      this.playerModel.play(0, true)
189      this.isSwitching = false
190    })
191  },
192  onNextClick() {
193    if (this.isSwitching) {
194      logger.info(TAG, `onNextClick ignored, isSwitching`)
195      return
196    }
197    logger.info(TAG, `onNextClick`)
198    this.playerModel.index++
199    if (this.playerModel.index >= this.playerModel.playlist.audioFiles.length) {
200      this.playerModel.index = 0
201    }
202    this.currentProgress = 0
203    this.isSwitching = true
204    this.playerModel.preLoad(this.playerModel.index, () => {
205      this.refreshSongInfo(this.playerModel.index)
206      this.playerModel.play(0, true)
207      this.isSwitching = false
208    })
209  },
210  onPlayClick() {
211    if (this.isSwitching) {
212      logger.info(TAG, `onPlayClick ignored, isSwitching`)
213      return
214    }
215    logger.debug(TAG, `onPlayClick, isPlaying=${this.playerModel.isPlaying}`)
216    if (this.playerModel.isPlaying) {
217      this.playerModel.pause()
218    } else {
219      this.playerModel.preLoad(this.playerModel.index, () => {
220        this.playerModel.play(-1, true)
221      })
222    }
223  },
224  onContinueAbilityClick() {
225    logger.info(TAG, `onContinueAbilityClick begin`)
226    this.remoteDeviceModel.registerDeviceListCallback(() => {
227      logger.info(TAG, `registerDeviceListCallback, callback entered`)
228      var list = []
229      list[0] = DEVICE_LIST_LOCALHOST
230      var deviceList
231      if (this.remoteDeviceModel.discoverList.length > 0) {
232        deviceList = this.remoteDeviceModel.discoverList
233      } else {
234        deviceList = this.remoteDeviceModel.deviceList
235      }
236      logger.debug(TAG, `on remote device updated, count=${deviceList.length}`)
237      for (var i = 0; i < deviceList.length; i++) {
238        logger.debug(TAG, `device ${i}/${deviceList.length} deviceId=${deviceList[i].deviceId}` +
239        ` deviceName=${deviceList[i].deviceName} deviceType=${deviceList[i].deviceType}`)
240        list[i + 1] = {
241          name: deviceList[i].deviceName,
242          id: deviceList[i].deviceId,
243        }
244      }
245      this.deviceList = list
246    })
247    this.$element('continueAbilityDialog').show()
248    this.isDialogShowing = true
249    logger.info(TAG, `onContinueAbilityClick end`)
250  },
251  startAbilityContinuation(deviceId, deviceName) {
252    this.$element('continueAbilityDialog').close()
253    var params
254    if (this.playerModel.index >= 0 && this.playerModel.index <= this.playerModel.playlist.audioFiles.length) {
255      params = {
256        uri: this.playerModel.playlist.audioFiles[this.playerModel.index].fileUri,
257        seekTo: this.playerModel.getCurrentMs(),
258        isPlaying: this.playerModel.isPlaying
259      }
260    } else {
261      params = {
262        uri: '',
263        seekTo: 0,
264        isPlaying: false
265      }
266    }
267    logger.debug(TAG, `featureAbility.startAbility deviceId=${deviceId} deviceName=${deviceName}`)
268    var wantValue = {
269      bundleName: 'ohos.samples.distributedmusicplayer',
270      abilityName: 'ohos.samples.distributedmusicplayer.MainAbility',
271      deviceId: deviceId,
272      parameters: params
273    }
274    var timerId = setTimeout(() => {
275      logger.info(TAG, `onMessageReceiveTimeout, terminateSelf`)
276      featureAbility.terminateSelf((error) => {
277        logger.error(TAG, `terminateSelf finished, error=${error}`)
278      })
279    }, 3000)
280    this.kvStoreModel.setOnMessageReceivedListener(REMOTE_ABILITY_STARTED, () => {
281      logger.info(`OnMessageReceived, terminateSelf`)
282      clearTimeout(timerId)
283      featureAbility.terminateSelf((error) => {
284        logger.error(`terminateSelf finished, error=${error}`)
285      })
286    })
287    featureAbility.startAbility({
288      want: wantValue
289    }).then((data) => {
290      logger.debug(TAG, `featureAbility.startAbility finished, ${JSON.stringify(data)}`)
291    })
292    logger.debug(TAG, `featureAbility.startAbility want=${JSON.stringify(wantValue)}`)
293    logger.info(TAG, `featureAbility.startAbility end`)
294  },
295  onRadioChange(inputValue, e) {
296    logger.debug(TAG, `onRadioChange ${inputValue} ${e.value}`)
297    if (inputValue === e.value) {
298      if (e.value === 'localhost') {
299        this.$element('continueAbilityDialog').close()
300        return
301      }
302      if (this.remoteDeviceModel.discoverList.length > 0) {
303        logger.info(TAG, `continue to unauthed device`)
304        var name = null
305        for (var i = 0; i < this.remoteDeviceModel.discoverList.length; i++) {
306          if (this.remoteDeviceModel.discoverList[i].deviceId === e.value) {
307            name = this.remoteDeviceModel.discoverList[i].deviceName
308            break
309          }
310        }
311        if (name === null) {
312          logger.error(TAG, `onRadioChange failed, can not get name from discoverList`)
313          return
314        }
315        logger.debug(TAG, `onRadioChange name=${name}`)
316        this.$element('continueAbilityDialog').close()
317
318        this.remoteDeviceModel.authDevice(e.value, () => {
319          logger.info(TAG, `auth and online finished`)
320          for (i = 0; i < this.remoteDeviceModel.deviceList.length; i++) {
321            if (this.remoteDeviceModel.deviceList[i].deviceName === name) {
322              this.startAbilityContinuation(this.remoteDeviceModel.deviceList[i].networkId, this.remoteDeviceModel.deviceList[i].deviceName)
323            }
324          }
325        })
326      } else {
327        logger.info(TAG, `continue to authed device`)
328        for (i = 0; i < this.remoteDeviceModel.deviceList.length; i++) {
329          if (this.remoteDeviceModel.deviceList[i].deviceId === e.value) {
330            this.startAbilityContinuation(this.remoteDeviceModel.deviceList[i].networkId, this.remoteDeviceModel.deviceList[i].deviceName)
331          }
332        }
333      }
334    }
335  },
336  cancelDialog(e) {
337    this.remoteDeviceModel.unregisterDeviceListCallback()
338    this.isDialogShowing = false
339  },
340  onDismissDialogClicked(e) {
341    this.dismissDialog()
342  },
343  dismissDialog() {
344    this.$element('continueAbilityDialog').close()
345    this.remoteDeviceModel.unregisterDeviceListCallback()
346    this.isDialogShowing = false
347  }
348}
349