From 8b2ce21e1a5193527478e07ef6230ea80e30bdf8 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Thu, 5 Apr 2018 14:12:24 -0500 Subject: [PATCH] fix(RN): bundle sound files in release build On Android the files will be copied to the assets/sounds directory of the SDK bundle on build time. To play the "asset:/" prefix has to be used to locate the files correctly. On iOS each sound file must be added to the SDK's Xcode project in order to be bundled correctly. To playback we need to know the path of the SDK bundle which is now exposed by the AppInfo iOS module. --- android/sdk/build.gradle | 16 ++++++++++++++++ ios/Podfile.lock | 8 ++++---- ios/sdk/sdk.xcodeproj/project.pbxproj | 8 ++++++++ ios/sdk/src/AppInfo.m | 3 +++ package-lock.json | 6 +++--- package.json | 2 +- react/features/app/functions.native.js | 10 ++++++++++ .../base/media/components/native/Audio.js | 2 +- react/features/base/participants/middleware.js | 13 +++++-------- react/features/base/participants/sounds.js | 11 +++++++++++ .../features/base/participants/sounds.native.js | 13 ------------- react/features/base/participants/sounds.web.js | 11 ----------- react/features/base/sounds/actions.js | 12 ++++++------ react/features/base/sounds/functions.android.js | 9 +++++++++ react/features/base/sounds/functions.ios.js | 12 ++++++++++++ react/features/base/sounds/functions.web.js | 9 +++++++++ react/features/chat/middleware.js | 4 ++-- react/features/chat/sounds.web.js | 5 +++-- 18 files changed, 103 insertions(+), 51 deletions(-) create mode 100644 react/features/base/participants/sounds.js delete mode 100644 react/features/base/participants/sounds.native.js delete mode 100644 react/features/base/participants/sounds.web.js create mode 100644 react/features/base/sounds/functions.android.js create mode 100644 react/features/base/sounds/functions.ios.js create mode 100644 react/features/base/sounds/functions.web.js diff --git a/android/sdk/build.gradle b/android/sdk/build.gradle index dbf899a53..f5baa1e73 100644 --- a/android/sdk/build.gradle +++ b/android/sdk/build.gradle @@ -71,6 +71,22 @@ gradle.projectsEvaluated { runBefore("processUniversal${buildNameCapitalized}Resources", currentFontTask) runBefore("process${buildNameCapitalized}Resources", currentFontTask) + def currentSoundsTask = tasks.create( + name: "copy${buildNameCapitalized}Sounds", + type: Copy) { + from("${projectDir}/../../sounds/joined.wav") + from("${projectDir}/../../sounds/left.wav") + into("${bundlePath}/assets/sounds") + } + + currentSoundsTask.dependsOn("merge${buildNameCapitalized}Resources") + currentSoundsTask.dependsOn("merge${buildNameCapitalized}Assets") + + runBefore("processArmeabi-v7a${buildNameCapitalized}Resources", currentSoundsTask) + runBefore("processX86${buildNameCapitalized}Resources", currentSoundsTask) + runBefore("processUniversal${buildNameCapitalized}Resources", currentSoundsTask) + runBefore("process${buildNameCapitalized}Resources", currentSoundsTask) + // Bundle JavaScript and React resources. // (adapted from react-native/react.gradle) // diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1ce2fd402..571d3411a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -43,10 +43,10 @@ PODS: - React/Core - React/fishhook - React/RCTBlob - - RNSound (0.10.4): + - RNSound (0.10.9): - React/Core - - RNSound/Core (= 0.10.4) - - RNSound/Core (0.10.4): + - RNSound/Core (= 0.10.9) + - RNSound/Core (0.10.9): - React/Core - RNVectorIcons (4.4.2): - React @@ -103,7 +103,7 @@ SPEC CHECKSUMS: react-native-keep-awake: 0de4bd66de0c23178107dce0c2fcc3354b2a8e94 react-native-locale-detector: d1b2c6fe5abb56e3a1efb6c2d6f308c05c4251f1 react-native-webrtc: bc044ca9530fc802e7533f247aa08fe1b6bf8dc5 - RNSound: d0818fe2435254fe30540fae48a429c5ffb72e09 + RNSound: b360b3862d3118ed1c74bb9825696b5957686ac4 RNVectorIcons: c0dbfbf6068fefa240c37b0f71bd03b45dddac44 yoga: 17521bbb0dd54a47c0b3ac43253e78cdac7488e0 diff --git a/ios/sdk/sdk.xcodeproj/project.pbxproj b/ios/sdk/sdk.xcodeproj/project.pbxproj index f8e6c5f3a..b0d098d87 100644 --- a/ios/sdk/sdk.xcodeproj/project.pbxproj +++ b/ios/sdk/sdk.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BCA496B1EC4BBF900B793EE /* jitsi.ttf */; }; 0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */; }; + 75635B0A20751D6D00F29C9F /* joined.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0820751D6D00F29C9F /* joined.wav */; }; + 75635B0B20751D6D00F29C9F /* left.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0920751D6D00F29C9F /* left.wav */; }; C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; }; C6245F5E2053091D0040BE68 /* image-resize@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5C2053091D0040BE68 /* image-resize@3x.png */; }; C6A3425F204EF76800E062DD /* PiPWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425C204EF76800E062DD /* PiPWindow.swift */; }; @@ -60,6 +62,8 @@ 0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = ""; }; 0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 75635B0820751D6D00F29C9F /* joined.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = joined.wav; path = ../../sounds/joined.wav; sourceTree = ""; }; + 75635B0920751D6D00F29C9F /* left.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = left.wav; path = ../../sounds/left.wav; sourceTree = ""; }; 98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = ""; }; 9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = ""; }; C6245F5B2053091D0040BE68 /* image-resize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@2x.png"; path = "src/picture-in-picture/image-resize@2x.png"; sourceTree = ""; }; @@ -89,6 +93,8 @@ 0BCA49681EC4BBE500B793EE /* Resources */ = { isa = PBXGroup; children = ( + 75635B0820751D6D00F29C9F /* joined.wav */, + 75635B0920751D6D00F29C9F /* left.wav */, 0BC4B8681F8C01E100CE8B21 /* CallKitIcon.png */, C6245F5B2053091D0040BE68 /* image-resize@2x.png */, C6245F5C2053091D0040BE68 /* image-resize@3x.png */, @@ -252,6 +258,8 @@ 0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */, C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */, 0BC4B8691F8C03A700CE8B21 /* CallKitIcon.png in Resources */, + 75635B0B20751D6D00F29C9F /* left.wav in Resources */, + 75635B0A20751D6D00F29C9F /* joined.wav in Resources */, C6245F5E2053091D0040BE68 /* image-resize@3x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/sdk/src/AppInfo.m b/ios/sdk/src/AppInfo.m index 9db363894..61fc897b9 100644 --- a/ios/sdk/src/AppInfo.m +++ b/ios/sdk/src/AppInfo.m @@ -45,8 +45,11 @@ RCT_EXPORT_MODULE(); } } + NSString *sdkBundlePath = [[NSBundle bundleForClass:self.class] bundlePath]; + return @{ @"name": name, + @"sdkBundlePath": sdkBundlePath, @"version": version }; }; diff --git a/package-lock.json b/package-lock.json index 069219b1b..1959d1482 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10405,9 +10405,9 @@ "integrity": "sha1-QeDsKqfdjxLzo+6Dr51jxLZw+KE=" }, "react-native-sound": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/react-native-sound/-/react-native-sound-0.10.4.tgz", - "integrity": "sha512-V9v4CjKgv8ekQRLOJSoKA7pxJ03F4Ih3T/RfMIlMWLktz7v/O4sdJPjRBLOzZRqAnr9FWTLbSk1ZCjioXh3mjQ==" + "version": "0.10.9", + "resolved": "https://registry.npmjs.org/react-native-sound/-/react-native-sound-0.10.9.tgz", + "integrity": "sha1-awCw9K/QF83gn7udFx3xtdW4Uag=" }, "react-native-vector-icons": { "version": "4.4.2", diff --git a/package.json b/package.json index 0d71be086..a9304efc0 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "react-native-keep-awake": "2.0.6", "react-native-locale-detector": "github:jitsi/react-native-locale-detector#cc76092fc4335488a28a9529c8b50afae2c3ecdc", "react-native-prompt": "1.0.0", - "react-native-sound": "0.10.4", + "react-native-sound": "0.10.9", "react-native-vector-icons": "4.4.2", "react-native-webrtc": "github:jitsi/react-native-webrtc#84aee6693195c5be6b6f5f794a1e52dc7913fb3b", "react-redux": "5.0.6", diff --git a/react/features/app/functions.native.js b/react/features/app/functions.native.js index a4fd215bf..a83a8fc7b 100644 --- a/react/features/app/functions.native.js +++ b/react/features/app/functions.native.js @@ -11,3 +11,13 @@ export * from './getRouteToRender'; export function getName() { return NativeModules.AppInfo.name; } + +/** + * Returns the path to the Jitsi Meet SDK bundle on iOS. On Android it will be + * undefined. + * + * @returns {string|undefined} + */ +export function getSdkBundlePath() { + return NativeModules.AppInfo.sdkBundlePath; +} diff --git a/react/features/base/media/components/native/Audio.js b/react/features/base/media/components/native/Audio.js index b2979dab3..fa2ee4109 100644 --- a/react/features/base/media/components/native/Audio.js +++ b/react/features/base/media/components/native/Audio.js @@ -44,7 +44,7 @@ export default class Audio extends AbstractAudio { this._sound = this.props.src ? new Sound( - this.props.src, + this.props.src, null, this._soundLoadedCallback.bind(this)) : null; } diff --git a/react/features/base/participants/middleware.js b/react/features/base/participants/middleware.js index 2ce0f728b..ae1732b37 100644 --- a/react/features/base/participants/middleware.js +++ b/react/features/base/participants/middleware.js @@ -34,10 +34,7 @@ import { getParticipantById, getParticipantCount } from './functions'; -import { - PARTICIPANT_JOINED_SRC, - PARTICIPANT_LEFT_SRC -} from './sounds'; +import { PARTICIPANT_JOINED_FILE, PARTICIPANT_LEFT_FILE } from './sounds'; declare var APP: Object; @@ -214,9 +211,9 @@ function _maybePlaySounds({ getState, dispatch }, action) { */ function _registerSounds({ dispatch }) { dispatch( - registerSound(PARTICIPANT_JOINED_SOUND_ID, PARTICIPANT_JOINED_SRC)); + registerSound(PARTICIPANT_JOINED_SOUND_ID, PARTICIPANT_JOINED_FILE)); dispatch( - registerSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_SRC)); + registerSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_FILE)); } /** @@ -228,7 +225,7 @@ function _registerSounds({ dispatch }) { */ function _unregisterSounds({ dispatch }) { dispatch( - unregisterSound(PARTICIPANT_JOINED_SOUND_ID, PARTICIPANT_JOINED_SRC)); + unregisterSound(PARTICIPANT_JOINED_SOUND_ID)); dispatch( - unregisterSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_SRC)); + unregisterSound(PARTICIPANT_LEFT_SOUND_ID)); } diff --git a/react/features/base/participants/sounds.js b/react/features/base/participants/sounds.js new file mode 100644 index 000000000..9e71942ee --- /dev/null +++ b/react/features/base/participants/sounds.js @@ -0,0 +1,11 @@ +/** + * The name of the bundled sound file which will be played when new participant + * joins the conference. + */ +export const PARTICIPANT_JOINED_FILE = 'joined.wav'; + +/** + * The name of the bundled sound file which will be played when any participant + * leaves the conference. + */ +export const PARTICIPANT_LEFT_FILE = 'left.wav'; diff --git a/react/features/base/participants/sounds.native.js b/react/features/base/participants/sounds.native.js deleted file mode 100644 index 3940b9348..000000000 --- a/react/features/base/participants/sounds.native.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Points to the sound file which will be played when new participant joins - * the conference. - */ -export const PARTICIPANT_JOINED_SRC - = require('../../../../sounds/joined.wav'); - -/** - * Points to the sound file which will be played when any participant leaves - * the conference. - */ -export const PARTICIPANT_LEFT_SRC - = require('../../../../sounds/left.wav'); diff --git a/react/features/base/participants/sounds.web.js b/react/features/base/participants/sounds.web.js deleted file mode 100644 index c2eca1732..000000000 --- a/react/features/base/participants/sounds.web.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Points to the sound file which will be played when new participant joins - * the conference. - */ -export const PARTICIPANT_JOINED_SRC = 'sounds/joined.wav'; - -/** - * Points to the sound file which will be played when any participant leaves - * the conference. - */ -export const PARTICIPANT_LEFT_SRC = 'sounds/left.wav'; diff --git a/react/features/base/sounds/actions.js b/react/features/base/sounds/actions.js index 851e4d786..a0c8c696a 100644 --- a/react/features/base/sounds/actions.js +++ b/react/features/base/sounds/actions.js @@ -9,6 +9,7 @@ import { REGISTER_SOUND, UNREGISTER_SOUND } from './actionTypes'; +import { getSoundsPath } from './functions'; /** * Adds {@link AudioElement} instance to the base/sounds feature state for the @@ -81,20 +82,19 @@ export function playSound(soundId: string): Object { * * @param {string} soundId - The global identifier which identify the sound * created for given source object. - * @param {Object|string} src - Either path to an audio file or a raw object - * which specifies the audio resource that will be associated with the given - * {@code soundId}. + * @param {string} soundName - The name of bundled audio file that will be + * associated with the given {@code soundId}. * @returns {{ * type: REGISTER_SOUND, * soundId: string, - * src: (Object | string) + * src: string * }} */ -export function registerSound(soundId: string, src: Object | string): Object { +export function registerSound(soundId: string, soundName: string): Object { return { type: REGISTER_SOUND, soundId, - src + src: `${getSoundsPath()}/${soundName}` }; } diff --git a/react/features/base/sounds/functions.android.js b/react/features/base/sounds/functions.android.js new file mode 100644 index 000000000..df99d970c --- /dev/null +++ b/react/features/base/sounds/functions.android.js @@ -0,0 +1,9 @@ +/** + * Returns the location of the sounds. On Android sounds files are copied to + * the 'assets/sounds/' folder of the SDK bundle on build time. + * + * @returns {string} + */ +export function getSoundsPath() { + return 'asset:/sounds'; +} diff --git a/react/features/base/sounds/functions.ios.js b/react/features/base/sounds/functions.ios.js new file mode 100644 index 000000000..bfdb5037e --- /dev/null +++ b/react/features/base/sounds/functions.ios.js @@ -0,0 +1,12 @@ +import { getSdkBundlePath } from '../../app'; + +/** + * Returns the location of the sounds. On iOS it's the location of the SDK + * bundle on the phone. Each sound file must be added to the SDK's XCode project + * in order to be bundled correctly. + * + * @returns {string} + */ +export function getSoundsPath() { + return getSdkBundlePath(); +} diff --git a/react/features/base/sounds/functions.web.js b/react/features/base/sounds/functions.web.js new file mode 100644 index 000000000..b4dba5281 --- /dev/null +++ b/react/features/base/sounds/functions.web.js @@ -0,0 +1,9 @@ +/** + * Returns the location of the sounds. On Web it's the relative path to + * the sounds folder placed in the source root. + * + * @returns {string} + */ +export function getSoundsPath() { + return 'sounds'; +} diff --git a/react/features/chat/middleware.js b/react/features/chat/middleware.js index cfa5b923c..45964ade9 100644 --- a/react/features/chat/middleware.js +++ b/react/features/chat/middleware.js @@ -7,7 +7,7 @@ import { MiddlewareRegistry } from '../base/redux'; import { playSound, registerSound, unregisterSound } from '../base/sounds'; import { INCOMING_MSG_SOUND_ID } from './constants'; -import { INCOMING_MSG_SOUND_SRC } from './sounds'; +import { INCOMING_MSG_SOUND_FILE } from './sounds'; declare var APP: Object; @@ -24,7 +24,7 @@ MiddlewareRegistry.register(store => next => action => { // on mobile. typeof APP === 'undefined' || store.dispatch( - registerSound(INCOMING_MSG_SOUND_ID, INCOMING_MSG_SOUND_SRC)); + registerSound(INCOMING_MSG_SOUND_ID, INCOMING_MSG_SOUND_FILE)); break; case APP_WILL_UNMOUNT: diff --git a/react/features/chat/sounds.web.js b/react/features/chat/sounds.web.js index 486ad14db..1b113cb50 100644 --- a/react/features/chat/sounds.web.js +++ b/react/features/chat/sounds.web.js @@ -1,6 +1,7 @@ /** - * The audio source for the incoming chat message sound. + * The name of the bundled audio file which will be played for the incoming chat + * message sound. * * @type {string} */ -export const INCOMING_MSG_SOUND_SRC = 'sounds/incomingMessage.wav'; +export const INCOMING_MSG_SOUND_FILE = 'incomingMessage.wav';