Sound refactor (#1589)
* Soud refactor * remove files from files_common * add timeout to set_volumn * add param volume to init * done * test.cc * fix typo * add repeat param instead of loop * revert submodule * add member function currentSound * remove function create_player from class member * fix build error fix repeat * rename CHECK_RESULT to ReturnOnError * set currentSound_ before posible err * use std::map to initialize sound table cleanup cleanup cleanup fix bug in stop change paramater name * done * remove function CreatePlayer, create player in init() * resolve conflict * remove sound test * rebase * remove whitespace * Apply great review suggestion * use player's SLVolumeItf interface to set volume * use float * leave the volume control the way it ispull/1711/head
parent
10cb6ab87a
commit
8cacc14b31
11 changed files with 159 additions and 377 deletions
@ -1,184 +0,0 @@ |
||||
#include <stdio.h> |
||||
#include <assert.h> |
||||
#include <unistd.h> |
||||
#include <stdlib.h> |
||||
#include <getopt.h> |
||||
|
||||
#include "common/timing.h" |
||||
#include "slplay.h" |
||||
|
||||
SLEngineItf engineInterface = NULL; |
||||
SLObjectItf outputMix = NULL; |
||||
SLObjectItf engine = NULL; |
||||
uri_player players[32] = {{NULL, NULL, NULL}}; |
||||
|
||||
uint64_t loop_start = 0; |
||||
uint64_t loop_start_ctx = 0; |
||||
|
||||
uri_player* get_player_by_uri(const char* uri) { |
||||
for (uri_player *s = players; s->uri != NULL; s++) { |
||||
if (strcmp(s->uri, uri) == 0) { |
||||
return s; |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
uri_player* slplay_create_player_for_uri(const char* uri, char **error) { |
||||
uri_player player = { uri, NULL, NULL }; |
||||
|
||||
SLresult result; |
||||
SLDataLocator_URI locUri = {SL_DATALOCATOR_URI, (SLchar *) uri}; |
||||
SLDataFormat_MIME formatMime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; |
||||
SLDataSource audioSrc = {&locUri, &formatMime}; |
||||
|
||||
SLDataLocator_OutputMix outMix = {SL_DATALOCATOR_OUTPUTMIX, outputMix}; |
||||
SLDataSink audioSnk = {&outMix, NULL}; |
||||
|
||||
result = (*engineInterface)->CreateAudioPlayer(engineInterface, &player.player, &audioSrc, &audioSnk, 0, NULL, NULL); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to create audio player"; |
||||
return NULL; |
||||
} |
||||
|
||||
result = (*(player.player))->Realize(player.player, SL_BOOLEAN_FALSE); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to realize audio player"; |
||||
return NULL; |
||||
} |
||||
|
||||
result = (*(player.player))->GetInterface(player.player, SL_IID_PLAY, &(player.playInterface)); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to get player interface"; |
||||
return NULL; |
||||
} |
||||
|
||||
result = (*(player.playInterface))->SetPlayState(player.playInterface, SL_PLAYSTATE_PAUSED); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to initialize playstate to SL_PLAYSTATE_PAUSED"; |
||||
return NULL; |
||||
} |
||||
|
||||
uri_player *p = players; |
||||
while (p->uri != NULL) { |
||||
p++; |
||||
} |
||||
*p = player; |
||||
|
||||
return p; |
||||
} |
||||
|
||||
void slplay_setup(char **error) { |
||||
SLresult result; |
||||
SLEngineOption engineOptions[] = {{SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE}}; |
||||
result = slCreateEngine(&engine, 1, engineOptions, 0, NULL, NULL); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to create OpenSL engine"; |
||||
} |
||||
|
||||
result = (*engine)->Realize(engine, SL_BOOLEAN_FALSE); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to realize OpenSL engine"; |
||||
} |
||||
|
||||
result = (*engine)->GetInterface(engine, SL_IID_ENGINE, &engineInterface); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to realize OpenSL engine"; |
||||
} |
||||
|
||||
const SLInterfaceID ids[1] = {SL_IID_VOLUME}; |
||||
const SLboolean req[1] = {SL_BOOLEAN_FALSE}; |
||||
result = (*engineInterface)->CreateOutputMix(engineInterface, &outputMix, 1, ids, req); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to create output mix"; |
||||
} |
||||
|
||||
result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to realize output mix"; |
||||
} |
||||
} |
||||
|
||||
void slplay_destroy() { |
||||
for (uri_player *player = players; player->uri != NULL; player++) { |
||||
if (player->player) { |
||||
(*(player->player))->Destroy(player->player); |
||||
} |
||||
} |
||||
|
||||
(*outputMix)->Destroy(outputMix); |
||||
(*engine)->Destroy(engine); |
||||
} |
||||
|
||||
void slplay_stop(uri_player* player, char **error) { |
||||
SLPlayItf playInterface = player->playInterface; |
||||
SLresult result; |
||||
|
||||
// stop a loop
|
||||
loop_start = 0; |
||||
|
||||
result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_PAUSED); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to set SL_PLAYSTATE_STOPPED"; |
||||
return; |
||||
} |
||||
} |
||||
|
||||
void slplay_stop_uri(const char* uri, char **error) { |
||||
uri_player* player = get_player_by_uri(uri); |
||||
slplay_stop(player, error); |
||||
} |
||||
|
||||
void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event) { |
||||
uint64_t cb_loop_start = *((uint64_t*)context); |
||||
if (event == SL_PLAYEVENT_HEADATEND && cb_loop_start == loop_start) { |
||||
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); |
||||
(*playItf)->SetMarkerPosition(playItf, 0); |
||||
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); |
||||
} |
||||
} |
||||
|
||||
void slplay_play (const char *uri, bool loop, char **error) { |
||||
SLresult result; |
||||
|
||||
uri_player* player = get_player_by_uri(uri); |
||||
if (player == NULL) { |
||||
player = slplay_create_player_for_uri(uri, error); |
||||
if (*error) { |
||||
return; |
||||
} |
||||
} |
||||
|
||||
SLPlayItf playInterface = player->playInterface; |
||||
if (loop) { |
||||
loop_start = nanos_since_boot(); |
||||
loop_start_ctx = loop_start; |
||||
result = (*playInterface)->RegisterCallback(playInterface, slplay_callback, &loop_start_ctx); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
char error[64]; |
||||
snprintf(error, sizeof(error), "Failed to register callback. %d", result); |
||||
*error = error[0]; |
||||
return; |
||||
} |
||||
|
||||
result = (*playInterface)->SetCallbackEventsMask(playInterface, SL_PLAYEVENT_HEADATEND); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to set callback event mask"; |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// Reset the audio player
|
||||
result = (*playInterface)->ClearMarkerPosition(playInterface); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to clear marker position"; |
||||
return; |
||||
} |
||||
result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_PAUSED); |
||||
result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_STOPPED); |
||||
result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_PLAYING); |
||||
if (result != SL_RESULT_SUCCESS) { |
||||
*error = "Failed to set SL_PLAYSTATE_PLAYING"; |
||||
} |
||||
} |
@ -1,21 +0,0 @@ |
||||
#ifndef SLPLAY_H |
||||
#define SLPLAY_H |
||||
|
||||
#include <SLES/OpenSLES.h> |
||||
#include <SLES/OpenSLES_Android.h> |
||||
#include <stdbool.h> |
||||
|
||||
typedef struct { |
||||
const char* uri; |
||||
SLObjectItf player; |
||||
SLPlayItf playInterface; |
||||
} uri_player; |
||||
|
||||
void slplay_setup(char **error); |
||||
uri_player* slplay_create_player_for_uri(const char* uri, char **error); |
||||
void slplay_play (const char *uri, bool loop, char **error); |
||||
void slplay_stop_uri (const char* uri, char **error); |
||||
void slplay_destroy(); |
||||
|
||||
#endif |
||||
|
@ -1,17 +1,33 @@ |
||||
#ifndef __SOUND_HPP |
||||
#define __SOUND_HPP |
||||
|
||||
#pragma once |
||||
#include <map> |
||||
#include "cereal/gen/cpp/log.capnp.h" |
||||
|
||||
typedef cereal::CarControl::HUDControl::AudibleAlert AudibleAlert; |
||||
|
||||
void ui_sound_init(); |
||||
void ui_sound_destroy(); |
||||
#if defined(QCOM) || defined(QCOM2) |
||||
#include <SLES/OpenSLES.h> |
||||
#include <SLES/OpenSLES_Android.h> |
||||
#endif |
||||
|
||||
void set_volume(int volume); |
||||
typedef cereal::CarControl::HUDControl::AudibleAlert AudibleAlert; |
||||
|
||||
void play_alert_sound(AudibleAlert alert); |
||||
void stop_alert_sound(AudibleAlert alert); |
||||
class Sound { |
||||
public: |
||||
Sound() = default; |
||||
bool init(int volume); |
||||
bool play(AudibleAlert alert, int repeat = 0); |
||||
void stop(); |
||||
void setVolume(int volume, int timeout_seconds = 5); |
||||
AudibleAlert currentPlaying(); |
||||
~Sound(); |
||||
|
||||
private: |
||||
#if defined(QCOM) || defined(QCOM2) |
||||
SLObjectItf engine_ = nullptr; |
||||
SLObjectItf outputMix_ = nullptr; |
||||
int last_volume_ = 0; |
||||
double last_set_volume_time_ = 0.; |
||||
AudibleAlert currentSound_ = AudibleAlert::NONE; |
||||
struct Player; |
||||
std::map<AudibleAlert, Player *> player_; |
||||
friend void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event); |
||||
#endif |
||||
|
||||
}; |
||||
|
@ -1,3 +0,0 @@ |
||||
#!/bin/sh |
||||
clang -fPIC -o play_sound play_sound.c ../slplay.c -I ../../ -I ../ -lOpenSLES -Wl,-rpath=/system/lib64 |
||||
|
@ -1,37 +0,0 @@ |
||||
#include <stdio.h> |
||||
#include "slplay.h" |
||||
|
||||
void play_sound(char *uri, int volume) { |
||||
char **error = NULL; |
||||
printf("call slplay_setup\n"); |
||||
slplay_setup(error); |
||||
if (error) { printf("%s\n", *error); return; } |
||||
|
||||
printf("call slplay_create_player_for_uri\n"); |
||||
slplay_create_player_for_uri(uri, error); |
||||
if (error) { printf("%s\n", *error); return; } |
||||
|
||||
printf("call slplay_play\n"); |
||||
|
||||
while (1) { |
||||
char volume_change_cmd[64]; |
||||
sprintf(volume_change_cmd, "service call audio 3 i32 3 i32 %d i32 1", volume); |
||||
system(volume_change_cmd); |
||||
|
||||
slplay_play(uri, false, error); |
||||
if (error) { printf("%s\n", *error); return; } |
||||
|
||||
sleep(1); |
||||
} |
||||
} |
||||
|
||||
int main(int argc, char *argv[]) { |
||||
int volume = 10; |
||||
if (argc > 2) { |
||||
volume = atoi(argv[2]); |
||||
} |
||||
printf("setting volume to %d\n", volume); |
||||
|
||||
play_sound(argv[1], volume); |
||||
return 0; |
||||
} |
Loading…
Reference in new issue