1/*
2 * Copyright (C) 2024 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 router from '@ohos.router'
17import audio from '@ohos.multimedia.audio'
18import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager'
19import { BusinessError } from '@ohos.base'
20import fs from '@ohos.file.fs';
21import wantAgent from '@ohos.app.ability.wantAgent'
22import ohosWantAgent from '@ohos.wantAgent'
23import AVSessionManager from '@ohos.multimedia.avsession';
24import common from '@ohos.app.ability.common'
25import Want from '@ohos.app.ability.Want'
26
27let mXComponentController: XComponentController = new XComponentController()
28
29@Entry
30@Component
31struct Index {
32  @State message: string = 'Next Page'
33  @State imageLoadSuccess: string = "LoadFalse"
34  abilityContext: common.UIAbilityContext = AppStorage.get<common.UIAbilityContext>('EntryAbilityContext') as common.UIAbilityContext
35  audioRenderer: audio.AudioRenderer = {} as audio.AudioRenderer
36  @State audioStateText: string = 'Error'
37
38  async aboutToAppear() {
39    this.audioRenderer = await this.getAudioRenderer()
40  }
41
42  async onPageShow() {
43    this.audioStateText = this.audioRenderer ? this.audioRenderer.state.toString() : 'Error'
44  }
45
46  build() {
47    Row() {
48      Column() {
49        Button(this.message)
50          .id('firstButton')
51          .fontSize(50)
52          .fontWeight(FontWeight.Bold)
53          .onClick(() => {
54            router.pushUrl({ url: "pages/SecondPage" })
55          })
56        Text($r('app.string.Multilingual_Text'))
57          .id('multilingualText')
58          .fontSize(50)
59          .fontWeight(FontWeight.Bold)
60        Image($rawfile('test.png'))
61          .id('image')
62          .height('20%')
63          .onComplete((event) => {
64            this.imageLoadSuccess = "LoadSuccess"
65          })
66        Text(this.imageLoadSuccess.toString())
67          .id('imageLoadSuccess')
68          .fontSize(50)
69          .fontWeight(FontWeight.Bold)
70        XComponent({
71          id: '',
72          type: 'surface',
73          libraryname: '',
74          controller: mXComponentController
75        }).onLoad(() => {
76          mXComponentController.setXComponentSurfaceSize({ surfaceWidth: 500, surfaceHeight: 500 })
77        })
78          .width('30%')
79          .height('30%')
80
81        Text(mXComponentController.getXComponentSurfaceId())
82          .id("surfaceId")
83
84        Button('StartAudio')
85          .id('StartAudio')
86          .fontSize(20)
87          .onClick(async () => {
88            let res = await this.startAudio(this.audioRenderer, this.abilityContext)
89            this.audioStateText = this.audioRenderer ? this.audioRenderer.state.toString() : 'Error'
90          })
91        Button('StopAudio')
92          .id('StopAudio')
93          .fontSize(20)
94          .onClick(async () => {
95            let res = await this.stopAudio(this.audioRenderer, this.abilityContext)
96            this.audioStateText = this.audioRenderer ? this.audioRenderer.state.toString() : 'Error'
97          })
98        Text(this.audioStateText)
99          .id('AudioStateText')
100      }
101      .width('100%')
102    }
103    .height('100%')
104  }
105
106  async startAudio(audioRenderer: audio.AudioRenderer, abilityContext: common.UIAbilityContext) {
107    if (!audioRenderer) {
108      return false
109    }
110    try {
111      await audioRenderer.start()
112      let type: AVSessionManager.AVSessionType = 'audio';
113      let session = await AVSessionManager.createAVSession(abilityContext, 'AVSession', type);
114      await session.activate()
115    } catch (error) {
116      let err: BusinessError = error as BusinessError
117      console.error(`Start audioRenderer Fail. Code: ${err.code}, message: ${err.message}`)
118      return false
119    }
120    let wantAgentInfo: wantAgent.WantAgentInfo = {
121      wants: [
122        {
123          bundleName: 'com.acts.pcs.arktstest',
124          abilityName: 'EntryAbility'
125        } as Want
126      ],
127      requestCode: 0,
128      operationType: ohosWantAgent.OperationType.START_ABILITIES,
129      wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
130    }
131    try {
132      let wantAgentObj = await wantAgent.getWantAgent(wantAgentInfo)
133      await backgroundTaskManager.startBackgroundRunning(abilityContext,
134        backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK, wantAgentObj)
135    } catch (error) {
136      let err: BusinessError = error as BusinessError
137      console.error(`Start BackgroundRunning Fail. Code: ${err.code}, message: ${err.message}`)
138      return false
139    }
140    return true
141  }
142
143  async stopAudio(audioRenderer: audio.AudioRenderer, abilityContext: common.UIAbilityContext) {
144    if (!audioRenderer) {
145      return false
146    }
147    try {
148      audioRenderer.stop()
149      audioRenderer.release()
150    } catch (error) {
151      let err: BusinessError = error as BusinessError
152      console.error(`Stop audioRenderer Fail. Code: ${err.code}, message: ${err.message}`)
153      return false
154    }
155    try {
156      await backgroundTaskManager.stopBackgroundRunning(abilityContext)
157    } catch (error) {
158      let err: BusinessError = error as BusinessError
159      console.error(`Stop BackgroundRunning Fail. Code: ${err.code}, message: ${err.message}`)
160      return false
161    }
162    return true
163  }
164
165  async getAudioRenderer() {
166    try {
167      let audioStreamInfo: audio.AudioStreamInfo = {
168        samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000,
169        channels: audio.AudioChannel.CHANNEL_2,
170        sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
171        encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
172      }
173      let audioRendererInfo: audio.AudioRendererInfo = {
174        usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
175        rendererFlags: 0
176      }
177      let audioRendererOptions: audio.AudioRendererOptions = {
178        streamInfo: audioStreamInfo,
179        rendererInfo: audioRendererInfo
180      }
181      let audioRenderer: audio.AudioRenderer = await audio.createAudioRenderer(audioRendererOptions)
182      let bufferSize: number = 0
183      class Options {
184        offset?: number
185        length?: number
186      }
187      let writeDataCallback = (buffer: ArrayBuffer) => {
188        let path = '/data/storage/el2/base/haps/entry/files/'
189        let filePath = path + '/Believer.wav'
190        let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_ONLY)
191        let options: Options = {
192          offset: bufferSize,
193          length: buffer.byteLength
194        }
195        fs.readSync(file.fd, buffer, options)
196        bufferSize += buffer.byteLength
197      }
198      audioRenderer.on('writeData', writeDataCallback)
199      return audioRenderer
200    } catch (error) {
201      let err: BusinessError = error as BusinessError
202      console.error(`Create audioRenderer Fail. Code: ${err.code}, message: ${err.message}`)
203      return {} as audio.AudioRenderer
204    }
205  }
206}