Agora using wrong speaker on iOS device (Unity) - agora.io

Upon Initializing
// init engine
mRtcEngine = IRtcEngine.GetEngine(appId);
if (mRtcEngine == null)
return;
mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_GAME);
mRtcEngine.SetClientRole(CLIENT_ROLE.BROADCASTER);
// set callbacks (optional)
mRtcEngine.OnJoinChannelSuccess = onJoinChannelSuccess;
mRtcEngine.OnUserJoined = onUserJoined;
mRtcEngine.OnUserOffline = onUserOffline;
mRtcEngine.EnableWebSdkInteroperability(true);
mRtcEngine.OnRemoteVideoStateChanged = OnRemoteVideoStateChangedHandler;
mRtcEngine.DisableAudio();
mRtcEngine.EnableAudioVolumeIndication(500, 3, true);
mRtcEngine.EnableVideo();
mRtcEngine.EnableVideoObserver();
mRtcEngine.EnableLocalVideo(false);
mRtcEngine.SetDefaultAudioRouteToSpeakerphone(true);
mRtcEngine.AdjustRecordingSignalVolume(0);]
mRtcEngine.SetLogFilter(LOG_FILTER.DEBUG | LOG_FILTER.INFO | LOG_FILTER.WARNING | LOG_FILTER.ERROR |
LOG_FILTER.CRITICAL);
I call
mRtcEngine.SetDefaultAudioRouteToSpeakerphone(true);
After I call JoinChannel()
mRtcEngine.JoinChannel(channel, null, 0);
if (mRtcEngine.EnableVideoObserver() == Decimal.Zero)
{
mRtcEngine.EnableVideoObserver();
}
mRtcEngine.EnableAudio();
mRtcEngine.SetEnableSpeakerphone(true);
I call setEnableSpeakerphone(true)
but it still comes out of the ear speaker (as if its a phone call), am I missing a step?

The first set of code seems ok to me. But I think you should put the second set of code into the callback handler
// implement engine callbacks
private void onJoinChannelSuccess(string channelName, uint uid, int elapsed)
{
// mRtcEngine.EnableVideoObserver(); // you've called this!
mRtcEngine.EnableAudio();
mRtcEngine.SetEnableSpeakerphone(true);
}
I tried the code on iPhone and it came out from speaker. Note that you may want to use the demo app as the sender app to test this instead of this rewritten code.

switching from
mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_GAME);
to
mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_COMMUNICATION);
made it work. There is a note in the documentation that the gaming profile doesn't allow changes to the speaker.

Related

LUFA XInput Controller Endpoint IN/OUT not working

Intro:
I've been trying (and failing for four entire days straight so far) to get my Atmega32u4 device (Arduino Pro Micro) to emulate an Xbox controller.
It doesn't have to pretend it's an Xbox controller, but I need to communicate with the XInput driver, so emulating an official controller seemed like the best way to start.
The problem:
When using the code example XInputPadMicro by Bootsector it gets me exactly halfway. My device can either read OR write from/to the device driver. But not both. Getting both to work is essential to my project.
The code:
Device/Configuration descriptor can be found in XInputPadMicro (I
haven't changed these).
Configuration changed event:
Enabling the "OUT" endpoint will break the "IN" endpoint.
#define JOYSTICK_EPADDR_IN (ENDPOINT_DIR_IN | 1)
#define JOYSTICK_EPADDR_OUT (ENDPOINT_DIR_OUT | 1)
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_IN, EP_TYPE_INTERRUPT, 20, 1);
//If I enable this, the "IN" Endpoint will stop sending data.
//ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_OUT, EP_TYPE_INTERRUPT, 8, 1);
}
USB control request event:
void EVENT_USB_Device_ControlRequest(void)
{
/* Handle HID Class specific requests */
switch (USB_ControlRequest.bRequest)
{
case HID_REQ_GetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(&gamepad_state, 20);
Endpoint_ClearIN();
}
break;
case HID_REQ_SetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(&RXData, 8);
Endpoint_ClearOUT();
}
break;
}
}
HID Task (called every cycle):
void HID_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_OUT);
if (Endpoint_IsOUTReceived())
{
toggle = !toggle;
SetLED(LED3, toggle);
Endpoint_Read_Stream_LE(&RXData, 8, NULL);
SetLED(LED1, RXData[3] > 0 || RXData[4] > 0);
Endpoint_ClearOUT();
}
/* Select the Joystick Report Endpoint */
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_IN);
/* Check to see if the host is ready for another packet */
if (Endpoint_IsINReady())
{
/* Write Joystick Report Data */
Endpoint_Write_Stream_LE(&gamepad_state, 20, NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
}
Am I missing something crucial? Perhaps about the inner workings of the USB protocol? I am at a loss here.

Issue with syncing data between watch and phone

I have developed an Android App which runs on both a smartphone and a smartwatch in parallel. On both devices, (let's say) it reads certain sensor data, processes that data (calculate its mean), and then store that results. The watch sends this result to the phone so all storing takes place on the phone. I used buffer writer to write a number into a text file every 5 seconds.
Now after every 320 data items exchanges from watch to the phone, my app on the phone gets killed and I get "the name of the app" is unfortunately stopped as a message. I can't figure it what why they stop exactly after this time? The app running on the watch continues to work fine. However, I cannot store its data because it cannot communicate to the phone version so I get this message "the app is unfortunately stopped as a message" every time the watch sends a number to phone for storing. The app has one activity which has a service (foreground).
Could it be that there is a limit on the amount of data being shared?
The code on watch:
// Create a data map and put data in it
private void increaseCounter() {
PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
putDataMapReq.getDataMap().putInt(COUNT_KEY, count++); // I add current time here as well
PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult =
Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
}
Code on phone (possible problematic area):
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
// DataItem changed
DataItem item = event.getDataItem();
if (item.getUri().getPath().compareTo("/count") == 0) {
DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
updateCount(dataMap.getInt(COUNT_KEY));
}
} else if (event.getType() == DataEvent.TYPE_DELETED) {
// DataItem deleted
}
}
}
You have to use Service with StartForeground notification to be sure app is always working.
and try to use START_STICKY flag while staring.
UPDATE
You have to dealloc memory of dataevent:
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
try{
for(DataEvent dataEvent: dataEvents){
if(dataEvent.getType() != DataEvent.TYPE_CHANGED){
continue;
}
////... code
dataEvents.release();
}catch (Exception e){
Log.v("SunshineWatchFace",e.getMessage());
}
}

Notification when display gets connected or disconnected

I'm working on an OS X application that displays custom windows on all available spaces of all the connected displays.
I can get an array of the available display objects by calling [NSScreen screens].
What I'm currently missing is a way of telling if the user connects a display to or disconnects a screen from their system.
I have searched the Cocoa documentation for notifications that deal with a scenario like that without much luck, and I refuse to believe that there isn't some sort of system notification that gets posted when changing the number of displays connected to the system.
Any suggestions on how to solve this problem?
There are several ways to achieve that:
You could implement applicationDidChangeScreenParameters: in your app delegate (the method is part of the NSApplicationDelegateProtocol).
Another way is to listen for the NSApplicationDidChangeScreenParametersNotification sent by the default notification center [NSNotificationCenter defaultCenter].
Whenever your delegate method is called or you receive the notification, you can iterate over [NSScreen screens] and see if a display got connected or removed (you have to maintain a display list you can check against at program launch).
A non-Cocoa approach would be via Core Graphics Display services:
You have to implement a reconfiguration function and register it with CGDisplayRegisterReconfigurationCallback(CGDisplayReconfigurationCallBack cb, void* obj);
In your reconfiguration function you can query the state of the affected display. E.g.:
void DisplayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void* userInfo)
{
if(display == someDisplayYouAreInterestedIn)
{
if(flags & kCGDisplaySetModeFlag)
{
...
}
if(flags & kCGDisplayRemoveFlag)
{
...
}
if(flags & kCGDisplayDisabledFlag)
{
...
}
}
if(flags & kCGDisplaySetModeFlag || flags & kCGDisplayDisabledFlag || flags & kCGDisplayRemoveFlag)
{
...
}
}
in swift 3.0:
let nc = NotificationCenter.default
nc.addObserver(self,
selector: #selector(screenDidChange),
name: NSNotification.Name.NSApplicationDidChangeScreenParameters,
object: nil)
NC call back:
final func screenDidChange(notification: NSNotification){
let userInfo = notification.userInfo
print(userInfo)
}

Detect screen on/off from iOS service

I am developing a network monitor app that runs in background as a service. Is it possible to get a notification/call when the screen is turned on or off?
It exists in Android by using the following code:
private void registerScreenOnOffReceiver()
{
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenOnOffReceiver, filter);
}
screenOnOffReceiver is then called when screen is turned on/off. Is there a similar solution for iOS?
Edit:
The best I've found so far is UIApplicationProtectedDataWillBecomeUnavailable ( Detect if iPhone screen is on/off ) but it require the user to enable Data Protection (password protection) on the device.
You can use Darwin notifications, to listen for the events. I'm not 100% sure, but it looks to me, from running on a jailbroken iOS 5.0.1 iPhone 4, that one of these events might be what you need:
com.apple.iokit.hid.displayStatus
com.apple.springboard.hasBlankedScreen
com.apple.springboard.lockstate
Update: also, the following notification is posted when the phone locks (but not when it unlocks):
com.apple.springboard.lockcomplete
To use this, register for the event like this (this registers for just one event, but if that doesn't work for you, try the others):
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
NULL, // observer
displayStatusChanged, // callback
CFSTR("com.apple.iokit.hid.displayStatus"), // event name
NULL, // object
CFNotificationSuspensionBehaviorDeliverImmediately);
where displayStatusChanged is your event callback:
static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
NSLog(#"event received!");
// you might try inspecting the `userInfo` dictionary, to see
// if it contains any useful info
if (userInfo != nil) {
CFShow(userInfo);
}
}
If you really want this code to run in the background as a service, and you're jailbroken, I would recommend looking into iOS Launch Daemons. As opposed to an app that you simply let run in the background, a launch daemon can start automatically after a reboot, and you don't have to worry about iOS rules for apps running tasks in the background.
Let us know how this works!
Using the lower-level notify API you can query the lockstate when a notification is received:
#import <notify.h>
int notify_token;
notify_register_dispatch("com.apple.springboard.lockstate", &notify_token, dispatch_get_main_queue(), ^(int token) {
uint64_t state = UINT64_MAX;
notify_get_state(token, &state);
NSLog(#"com.apple.springboard.lockstate = %llu", state);
});
Of course your app will have to start a UIBackgroundTask in order to get the notifications, which limits the usefulness of this technique due to the limited runtime allowed by iOS.
While iPhone screen is locked appdelegate method
"- (void)applicationWillResignActive:(UIApplication *)application"
will be called you can check that. Hope it may help you.

Best way to know if application is inactive in cocoa mac OSX?

So, i am building a program that will stand on a exhibition for public usage, and i got a task to make a inactive state for it. Just display some random videos from a folder on the screen, like a screensaver but in the application.
So what is the best and proper way of checking if the user is inactive?
What i am thinking about is some kind of global timer that gets reset on every user input and if it reaches lets say 1 minute it goes into inactive mode. Are there any better ways?
You can use CGEventSourceSecondsSinceLastEventType
Returns the elapsed time since the last event for a Quartz event
source.
/*
To get the elapsed time since the previous input event—keyboard, mouse, or tablet—specify kCGAnyInputEventType.
*/
- (CFTimeInterval)systemIdleTime
{
CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
return timeSinceLastEvent;
}
I'm expanding on Parag Bafna's answer. In Qt you can do
#include <ApplicationServices/ApplicationServices.h>
double MyClass::getIdleTime() {
CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
return timeSinceLastEvent;
}
You also have to add the framework to your .pro file:
QMAKE_LFLAGS += -F/System/Library/Frameworks/ApplicationServices.framework
LIBS += -framework ApplicationServices
The documentation of the function is here
I've found a solution that uses the HID manager, this seems to be the way to do it in Cocoa. (There's another solution for Carbon, but it doesn't work for 64bit OS X.)
Citing Daniel Reese on the Dan and Cheryl's Place blog:
#include <IOKit/IOKitLib.h>
/*
Returns the number of seconds the machine has been idle or -1 on error.
The code is compatible with Tiger/10.4 and later (but not iOS).
*/
int64_t SystemIdleTime(void) {
int64_t idlesecs = -1;
io_iterator_t iter = 0;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching("IOHIDSystem"),
&iter) == KERN_SUCCESS)
{
io_registry_entry_t entry = IOIteratorNext(iter);
if (entry) {
CFMutableDictionaryRef dict = NULL;
kern_return_t status;
status = IORegistryEntryCreateCFProperties(entry,
&dict,
kCFAllocatorDefault, 0);
if (status == KERN_SUCCESS)
{
CFNumberRef obj = CFDictionaryGetValue(dict,
CFSTR("HIDIdleTime"));
if (obj) {
int64_t nanoseconds = 0;
if (CFNumberGetValue(obj,
kCFNumberSInt64Type,
&nanoseconds))
{
// Convert from nanoseconds to seconds.
idlesecs = (nanoseconds >> 30);
}
}
CFRelease(dict);
}
IOObjectRelease(entry);
}
IOObjectRelease(iter);
}
return idlesecs;
}
The code has been slightly modified, to make it fit into the 80-character limit of stackoverflow.
This might sound like a silly question; but why not just set up a screensaver, with a short fuse?
You can listen for the NSNotification named #"com.apple.screensaver.didstart" if you need to do any resets or cleanups when the user wanders away.
Edit: You could also set up the screen saver; wait for it to fire, and then do your own thing when it starts, stopping the screen saver when you display your own videos; but setting up a screen saver the proper way is probably a good idea.
Take a look at UKIdleTimer, maybe it's what you're looking for.