1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// The file defines the symbols from OpenSLES that android is using. It then
6// loads the library dynamically on first use.
7
8// The openSLES API is using constant as part of the API. This file will define
9// proxies for those constants and redefine those when the library is first
10// loaded. For this, it need to be able to change their content and so import
11// the headers without const.  This is correct because OpenSLES.h is a C API.
12#define const
13#include <SLES/OpenSLES.h>
14#include <SLES/OpenSLES_Android.h>
15#undef const
16
17#include "base/basictypes.h"
18#include "base/files/file_path.h"
19#include "base/logging.h"
20#include "base/native_library.h"
21
22// The constants used in chromium. SLInterfaceID is actually a pointer to
23// SLInterfaceID_. Those symbols are defined as extern symbols in the OpenSLES
24// headers. They will be initialized to their correct values when the library is
25// loaded.
26SLInterfaceID SL_IID_ENGINE = NULL;
27SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE = NULL;
28SLInterfaceID SL_IID_ANDROIDCONFIGURATION = NULL;
29SLInterfaceID SL_IID_RECORD = NULL;
30SLInterfaceID SL_IID_BUFFERQUEUE = NULL;
31SLInterfaceID SL_IID_VOLUME = NULL;
32SLInterfaceID SL_IID_PLAY = NULL;
33
34namespace {
35
36// The name of the library to load.
37const char kOpenSLLibraryName[] = "libOpenSLES.so";
38
39// Loads the OpenSLES library, and initializes all the proxies.
40base::NativeLibrary IntializeLibraryHandle() {
41  base::NativeLibrary handle =
42      base::LoadNativeLibrary(base::FilePath(kOpenSLLibraryName), NULL);
43  DCHECK(handle) << "Unable to load " << kOpenSLLibraryName;
44
45  // Setup the proxy for each symbol.
46  // Attach the symbol name to the proxy address.
47  struct SymbolDefinition {
48    const char* name;
49    SLInterfaceID* sl_iid;
50  };
51
52  // The list of defined symbols.
53  const SymbolDefinition kSymbols[] = {
54      {"SL_IID_ENGINE", &SL_IID_ENGINE},
55      {"SL_IID_ANDROIDSIMPLEBUFFERQUEUE", &SL_IID_ANDROIDSIMPLEBUFFERQUEUE},
56      {"SL_IID_ANDROIDCONFIGURATION", &SL_IID_ANDROIDCONFIGURATION},
57      {"SL_IID_RECORD", &SL_IID_RECORD},
58      {"SL_IID_BUFFERQUEUE", &SL_IID_BUFFERQUEUE},
59      {"SL_IID_VOLUME", &SL_IID_VOLUME},
60      {"SL_IID_PLAY", &SL_IID_PLAY}
61  };
62
63  for (size_t i = 0; i < sizeof(kSymbols) / sizeof(kSymbols[0]); ++i) {
64    memcpy(kSymbols[i].sl_iid,
65           base::GetFunctionPointerFromNativeLibrary(handle, kSymbols[i].name),
66           sizeof(SLInterfaceID));
67    DCHECK(*kSymbols[i].sl_iid) << "Unable to find symbol for "
68                                << kSymbols[i].name;
69  }
70  return handle;
71}
72
73// Returns the handler to the shared library. The library itself will be lazily
74// loaded during the first call to this function.
75base::NativeLibrary LibraryHandle() {
76  // The handle is lazily initialized on the first call.
77  static base::NativeLibrary g_opensles_LibraryHandle =
78      IntializeLibraryHandle();
79  return g_opensles_LibraryHandle;
80}
81
82}  // namespace
83
84// Redefine slCreateEngine symbol.
85SLresult slCreateEngine(SLObjectItf* engine,
86                        SLuint32 num_options,
87                        SLEngineOption* engine_options,
88                        SLuint32 num_interfaces,
89                        SLInterfaceID* interface_ids,
90                        SLboolean* interfaces_required) {
91  typedef SLresult (*SlCreateEngineSignature)(SLObjectItf*,
92                                              SLuint32,
93                                              SLEngineOption*,
94                                              SLuint32,
95                                              SLInterfaceID*,
96                                              SLboolean*);
97  static SlCreateEngineSignature g_sl_create_engine_handle =
98      reinterpret_cast<SlCreateEngineSignature>(
99          base::GetFunctionPointerFromNativeLibrary(LibraryHandle(),
100                                                    "slCreateEngine"));
101  DCHECK(g_sl_create_engine_handle)
102      << "Unable to find symbol for slCreateEngine";
103  return g_sl_create_engine_handle(engine,
104                                   num_options,
105                                   engine_options,
106                                   num_interfaces,
107                                   interface_ids,
108                                   interfaces_required);
109}
110