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#include "btif_avrcp_audio_track.h"
19
20#include <media/AudioTrack.h>
21#include <utils/StrongPointer.h>
22
23#include "osi/include/log.h"
24
25using namespace android;
26
27typedef struct {
28    android::sp<android::AudioTrack> track;
29} BtifAvrcpAudioTrack;
30
31//#define DUMP_PCM_DATA TRUE
32#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
33FILE *outputPcmSampleFile;
34char outputFilename[50] = "/data/misc/bluedroid/output_sample.pcm";
35#endif
36
37void *BtifAvrcpAudioTrackCreate(int trackFreq, int channelType)
38{
39    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btCreateTrack freq %d  channel %d ",
40                     __func__, trackFreq, channelType);
41    sp<android::AudioTrack> track =
42        new android::AudioTrack(AUDIO_STREAM_MUSIC, trackFreq, AUDIO_FORMAT_PCM_16_BIT,
43                                channelType, (size_t) 0 /*frameCount*/,
44                                (audio_output_flags_t)AUDIO_OUTPUT_FLAG_FAST,
45                                NULL /*callback_t*/, NULL /*void* user*/, 0 /*notificationFrames*/,
46                                AUDIO_SESSION_ALLOCATE, android::AudioTrack::TRANSFER_SYNC);
47    assert(track != NULL);
48
49    BtifAvrcpAudioTrack *trackHolder = new BtifAvrcpAudioTrack;
50    assert(trackHolder != NULL);
51    trackHolder->track = track;
52
53    if (trackHolder->track->initCheck() != 0)
54    {
55        return nullptr;
56    }
57
58#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
59    outputPcmSampleFile = fopen(outputFilename, "ab");
60#endif
61    trackHolder->track->setVolume(1, 1);
62    return (void *)trackHolder;
63}
64
65void BtifAvrcpAudioTrackStart(void *handle)
66{
67    assert(handle != NULL);
68    BtifAvrcpAudioTrack *trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
69    assert(trackHolder != NULL);
70    assert(trackHolder->track != NULL);
71    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
72    trackHolder->track->start();
73}
74
75void BtifAvrcpAudioTrackStop(void *handle)
76{
77    if (handle == NULL) {
78        LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
79        return;
80    }
81    BtifAvrcpAudioTrack *trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
82    if (trackHolder != NULL && trackHolder->track != NULL) {
83        LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
84        trackHolder->track->stop();
85    }
86}
87
88void BtifAvrcpAudioTrackDelete(void *handle)
89{
90    if (handle == NULL) {
91        LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
92        return;
93    }
94    BtifAvrcpAudioTrack *trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
95    if (trackHolder != NULL && trackHolder->track != NULL) {
96        LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
97        delete trackHolder;
98    }
99
100#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
101    if (outputPcmSampleFile)
102    {
103        fclose(outputPcmSampleFile);
104    }
105    outputPcmSampleFile = NULL;
106#endif
107}
108
109void BtifAvrcpAudioTrackPause(void *handle)
110{
111    if (handle == NULL) {
112        LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
113        return;
114    }
115    BtifAvrcpAudioTrack *trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
116    if (trackHolder != NULL && trackHolder->track != NULL) {
117        LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
118        trackHolder->track->pause();
119        trackHolder->track->flush();
120    }
121}
122
123void BtifAvrcpSetAudioTrackGain(void *handle, float gain)
124{
125    if (handle == NULL) {
126        LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
127        return;
128    }
129    BtifAvrcpAudioTrack *trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
130    if (trackHolder != NULL && trackHolder->track != NULL) {
131        LOG_VERBOSE(LOG_TAG, "%s set gain %f", __func__, gain);
132        trackHolder->track->setVolume(gain);
133    }
134}
135
136int BtifAvrcpAudioTrackWriteData(void *handle, void *audioBuffer, int bufferlen)
137{
138    BtifAvrcpAudioTrack *trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
139    assert(trackHolder != NULL);
140    assert(trackHolder->track != NULL);
141    int retval = -1;
142#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
143    if (outputPcmSampleFile)
144    {
145        fwrite ((audioBuffer), 1, (size_t)bufferlen, outputPcmSampleFile);
146    }
147#endif
148    retval = trackHolder->track->write(audioBuffer, (size_t)bufferlen);
149    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btWriteData len = %d ret = %d",
150                     __func__, bufferlen, retval);
151    return retval;
152}
153