1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "bt_btif_avrcp_audio_track"
19
20#include "btif_avrcp_audio_track.h"
21
22#include <base/logging.h>
23#include <media/AudioTrack.h>
24#include <utils/StrongPointer.h>
25
26#include "bt_target.h"
27#include "osi/include/log.h"
28
29using namespace android;
30
31typedef struct { android::sp<android::AudioTrack> track; } BtifAvrcpAudioTrack;
32
33#if (DUMP_PCM_DATA == TRUE)
34FILE* outputPcmSampleFile;
35char outputFilename[50] = "/data/misc/bluedroid/output_sample.pcm";
36#endif
37
38void* BtifAvrcpAudioTrackCreate(int trackFreq, int channelType) {
39  LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btCreateTrack freq %d  channel %d ",
40              __func__, trackFreq, channelType);
41  sp<android::AudioTrack> track = new android::AudioTrack(
42      AUDIO_STREAM_MUSIC, trackFreq, AUDIO_FORMAT_PCM_16_BIT, channelType,
43      (size_t)0 /*frameCount*/, (audio_output_flags_t)AUDIO_OUTPUT_FLAG_FAST,
44      NULL /*callback_t*/, NULL /*void* user*/, 0 /*notificationFrames*/,
45      AUDIO_SESSION_ALLOCATE, android::AudioTrack::TRANSFER_SYNC);
46  CHECK(track != NULL);
47
48  BtifAvrcpAudioTrack* trackHolder = new BtifAvrcpAudioTrack;
49  CHECK(trackHolder != NULL);
50  trackHolder->track = track;
51
52  if (trackHolder->track->initCheck() != 0) {
53    return nullptr;
54  }
55
56#if (DUMP_PCM_DATA == TRUE)
57  outputPcmSampleFile = fopen(outputFilename, "ab");
58#endif
59  trackHolder->track->setVolume(1, 1);
60  return (void*)trackHolder;
61}
62
63void BtifAvrcpAudioTrackStart(void* handle) {
64  if (handle == NULL) {
65    LOG_ERROR(LOG_TAG, "%s: handle is null!", __func__);
66    return;
67  }
68  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
69  CHECK(trackHolder != NULL);
70  CHECK(trackHolder->track != NULL);
71  LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
72  trackHolder->track->start();
73}
74
75void BtifAvrcpAudioTrackStop(void* handle) {
76  if (handle == NULL) {
77    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
78    return;
79  }
80  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
81  if (trackHolder != NULL && trackHolder->track != NULL) {
82    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
83    trackHolder->track->stop();
84  }
85}
86
87void BtifAvrcpAudioTrackDelete(void* handle) {
88  if (handle == NULL) {
89    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
90    return;
91  }
92  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
93  if (trackHolder != NULL && trackHolder->track != NULL) {
94    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
95    delete trackHolder;
96  }
97
98#if (DUMP_PCM_DATA == TRUE)
99  if (outputPcmSampleFile) {
100    fclose(outputPcmSampleFile);
101  }
102  outputPcmSampleFile = NULL;
103#endif
104}
105
106void BtifAvrcpAudioTrackPause(void* handle) {
107  if (handle == NULL) {
108    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
109    return;
110  }
111  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
112  if (trackHolder != NULL && trackHolder->track != NULL) {
113    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
114    trackHolder->track->pause();
115    trackHolder->track->flush();
116  }
117}
118
119void BtifAvrcpSetAudioTrackGain(void* handle, float gain) {
120  if (handle == NULL) {
121    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
122    return;
123  }
124  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
125  if (trackHolder != NULL && trackHolder->track != NULL) {
126    LOG_VERBOSE(LOG_TAG, "%s set gain %f", __func__, gain);
127    trackHolder->track->setVolume(gain);
128  }
129}
130
131int BtifAvrcpAudioTrackWriteData(void* handle, void* audioBuffer,
132                                 int bufferlen) {
133  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
134  CHECK(trackHolder != NULL);
135  CHECK(trackHolder->track != NULL);
136  int retval = -1;
137#if (DUMP_PCM_DATA == TRUE)
138  if (outputPcmSampleFile) {
139    fwrite((audioBuffer), 1, (size_t)bufferlen, outputPcmSampleFile);
140  }
141#endif
142  retval = trackHolder->track->write(audioBuffer, (size_t)bufferlen);
143  LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btWriteData len = %d ret = %d", __func__,
144              bufferlen, retval);
145  return retval;
146}
147