AVMutableAudioMix simple question - xcode

just want to understand , what exactly I can do with this AVMutableAudioMix class, once I will insert PlayerItems (Assets) in to the AudioMix, can I play them one at the time or some of them at the same time with AVPlayer and change the parameters dynamically?

I think you might be visualizing it incorrectly. An AVMutableAudioMix instance is actually a property on the AVPlayerItem class. First grab the track of the asset using tracksWithMediaType: and create an AVMutableAudioMixInputParameters instance using audioMixInputParametersWithTrack:. Set any audio properties on that inputparameters instance, (for instance setVolume:atTime).
Then you need to add the input parameters onto an AVMutableAudioMix instance. Then you need to add this to an player item. I know this sounds confusing, but this is exactly how AVFoundation works with just about everything. There's terms flying around all over the place, but pretty much everything has a hierarchy.
So the general hierarchy is this: player->playerItem->audioMix->inputParameters. The code to ramp down the volume from the 5 to 7 second mark should look something like this:
AVAssetTrack *audioTrack = [[self.player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
AVMutableAudioMixInputParameters *params = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:audioTrack];
[params setVolumeRampFromStartVolume:1.0 toEndVolume:0.5 timeRange:CMTimeRangeMake(CMTimeMake(5,1), CMTimeMake(2,1))];
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = [NSArray arrayWithObject:params];
self.player.currentItem.audioMix = audioMix;
As far as doing this dynamically, you can, but only with local files (as opposed to streaming from the internet). I would probably try to keep this audioMix as an ivar and try resetting the params every time you want something to happen. If that doesn't work, you may have to create an instance of AVMutableAudioMix every time, not sure.
Also see this post and this.

Related

Animation played once godot

I want to play a little Animated Sprite once, I mean only when the scene is visited the first time. I am trying to connect some signals in those ways:
on_scene_ready():
Animated_sprite.play("animation_name")
on_Animated_sprite_animation_finished():
Animated_sprite.hide()
And that's working correctly. But it repeats every time the scene is entered.
I tried a solution found on another forum that seemed to me similar to my issue: put a global variable (but doesn't work and I bet I make it bad)
var has_not_played = true
on_scene_ready():
if has_not_played:
Animated_sprite.play(animation_name)
on_Animated_sprite_animation_finished():
Animated_sprite.hide()
has_not_played = false
Any suggestions?
Thanks.
As long as you create a new instance of the scene (what you most likely do, as we can see) your has_not_played variable will always be instanced as true as well. Setting it to false will not help here then.
One simple solution would be to create a autoload script to hold all level informations you need your programm to save, after the scene was exited.
These are infos you most likely want to save as well, when your game is saved.
As an example you could do something like this.
Create a script LevelInfos.gd. Mine looked like this:
extends Node
var level_infos : Dictionary = {
"level_1" : {
"start_animation_played" : false
}
}
Then add this to Project -> project settings -> Autoload with the NodeName LevelInfos.
Now you can reuse your existing code like this:
on_scene_ready():
if not LevelInfos.level_infos["level_1"]["start_animation_played"]:
Animated_sprite.play(animation_name)
on_Animated_sprite_animation_finished():
Animated_sprite.hide()
LevelInfos.level_infos["level_1"]["has_already_loaded"] = true
This should make it so it only gets played the first time the scene is visited, after you start the game.
Code wise I guess it would be better to make dedicated variables instead of using a dictionary, but it works as a example and could be easily saved as an JSON, if needed.

macOS command line app - User Defaults dictionaryRepresentation shows too many values

I a developing a macOS commandline application in Xcode, which uses User Defaults. I have the following code for my User Defaults
if let configDefaults = UserDefaults.init(suiteName: "com.tests.configuration") {
configDefaults.set("myStringValue", forKey: "stringKey")
configDefaults.synchronize()
print(configDefaults.dictionaryRepresentation())
}
This will create my own .plist file in the ~/Library/Preferences folder. If I look into the file, I can see only my single value which I added, which is perfectly fine. But when I call dictionaryRepresentation() on my UserDefaults object, the there are a lot of other attributes (I guess from the shared UserDefaults object), like
com.apple.trackpad.twoFingerFromRightEdgeSwipeGesture or AKLastEmailListRequestDateKey
Looking into the documentation of UserDefaults, it seems that this has to do with the search list of UserDefaults and that the standard object is in the search list:
func dictionaryRepresentation() -> [String : Any]
Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.
There are also the methods addSuite and removeSuite for a UserDefaults object, so I am guessing I need to remove the .standard suite from my configDefaults object, but I don't know the name, which should be used for that in the method.
Is it possible to remove the .standard defaults from the dictionary representation? I basically just want all of my own data in a dictionary, nothing more.
The reason I am trying to get only my values from the UserDefaults, is that a have a number of object of a custom type Connection (which store the configuration to connect to a server), which are saved in the UserDefaults. On program start I want to be able to load all objects into my app. Therefore I thought I could use dictionaryRepresentation(), as it would return all elements in the UserDefaults. But then there should be only my Connection objects in the dictionary, so that I can cast it to [String: Connection].
Given your purpose (in your latest edit of your question), what you should do is store a collection of Connection objects under a single key. Then, look up that key to get the collection.
It's not clear if the collection should be an array of Connection objects or a dictionary mapping strings to Connections. That's a choice you can make.
But, in any case, you shouldn't rely on the defaults being empty of everything else.
In other words, you would do:
UserDefaults.standard.set(yourStringToConnectionDictionary, forKey:"yourSingleKey")
and later:
let connectionMap = UserDefaults.dictionary(forKey:"yourSingleKey")
then look up Connections in the connectionMap by their name/ID/whatever.
Though the other solution proposed by Ken Thomases may be better from a design standpoint, I've found a solution that does exactly what I initially wanted. Calling
UserDefaults.standard.persistentDomain(forName: "com.company.TestApp.configuration")
Returns a dictionary containing only the values I've added to the domain com.company.TestApp.configuration, using
let configs = UserDefaults.init(suiteName: "com.company.TestApp.configuration")!
configs.set(someData, forKey: someKey)
Strangely in the Apple documentation says this about persistentDomain(forName:):
Calling this method is equivalent to initializing a user defaults object with init(suiteName:) passing domainName and calling the dictionaryRepresentation() method on it.
But this is not the case (see my question). Clarification on that subject is more than welcome.

RKClient: how do do a simple PUT of xml body

I'm using RestKit, and have yet to come across how to do a simple PUT of a body like this:
<parameters></parameters>
Can someone please give a code example?
This is kind of a confusing PUT since your query parameter is actually titled "parameters". Are you sure that was the intention? Try something like this.
NSDictionary* params = [NSDictionary dictionaryWithObject:#"" forKey:#"parameters"];
[[RKClient sharedClient] put:yourURL params:params delegate:self];
Of course you will need to have RestKit imported, and your .h file must accept < RKRequestDelegate >. I hope that gets you on the right track.
You may also want to look at this SO question, however I haven't implemented the suggested solution so I can't ascertain as to its efficacy.

RestKit many-to-many with Core Data: it works, but am I doing it right?

I'm new to RestKit. I'm trying to map a many-to-many relationship, between entities Space and User. For the purposes of this question, assume all the Space objects are in the Core Data store correctly already.
In the REST API, I can make a single call to get all the users for a given space. First of all, when I initialise my network fetching class, I set up a mapping appropriate for parsing a list of users:
RKManagedObjectMapping *teamMapping = [RKManagedObjectMapping mappingForEntity:[NSEntityDescription entityForName:#"User" inManagedObjectContext:self.manager.objectStore.primaryManagedObjectContext] inManagedObjectStore:self.manager.objectStore];
[teamMapping mapKeyPath:#"id" toAttribute:#"userID"];
[teamMapping mapKeyPath:#"name" toAttribute:#"name"];
teamMapping.primaryKeyAttribute = #"userID";
[self.manager.mappingProvider setMapping:teamMapping forKeyPath:#"users.user"];
Then, to populate the links for the users to the spaces, I do this:
NSArray *spaces = [self.managedObjectContext executeFetchRequest:[NSFetchRequest fetchRequestWithEntityName:#"Space"] error:nil];
for (QBSpace *space in spaces)
{
[self.manager loadObjectsAtResourcePath:[NSString stringWithFormat:#"space/%#/users", space.wikiName] usingBlock:^(RKObjectLoader *loader) {
loader.onDidLoadObjects = ^(NSArray *objects){
space.team = nil;
for (QBUser *user in objects)
{
[space addTeamObject:user];
}
};
}];
}
That is, I manually add the space->user link based on the returned array of objects.
Is that the correct way to do it? It seems to work fine, but I'm worried I'm missing a trick with regards to RestKit doing things automatically.
The returned XML for the file in question looks like
<users type="array">
<user>
<id>aPrimaryKey</id>
<login>loginName</login>
<login_name warning="deprecated">loginName</login_name>
<name>Real Name</name>
</user>
So there is nothing in the returned file to indicate the space that I'm trying to link to: I passed that in in the URL I requested, but there's nothing in the returned document about it, which is why I came up with this block based solution.
To all the RestKit users, does this look like an acceptable way to form many-to-many links?
If it works, it's ok?
You could think about having a Space custom ManagedObject. Have it respond to the RKObjectLoaderDelegate.
Then, when you get the reply, you could trigger the loadAtResourcePath from within its
objectLoader:didLoadObject:(id)object or objectLoader:didLoadObjectDictionary:
methods.
You could also make your Space class respond to the delegates from User and then tie them into their space at that point?
It might be better, but that would depend on what you are trying to achieve. Food for thought anyway. :)

Get User Account Image

Simply: how do I get the user's account image?
I'm using Cocoa on Mac.
The Address Book method doesn't work if the user deletes the vcard.
I use the CBIdentity method that never breaks, as Dave says:
+ (NSImage *)userImage
{
CBIdentity *identity = [CBIdentity identityWithName:NSUserName() authority:[CBIdentityAuthority defaultIdentityAuthority]];
return [identity image];
}
In order to use CBIdentity you need to add the Collaboration Framework to your targets and use the following include directive
#import <Collaboration/Collaboration.h>
If you only want an image for the logged-in user, it's also possible to get it with a one-liner using AddressBook:
NSData *imgData = [[[ABAddressBook sharedAddressBook] me] imageData];
but I believe that this is not guaranteed to be the same as the log-in image.
If you can get a handle to a CSIdentityRef or a CBIdentity* that represents the user in question, then you can invoke the -[CBIdentity image] method to retrieve their account image.
Edit:
Here's a previous answer of mine that shows how to query for all standard user accounts on a system and convert them into CBIdentity objects: Get all Users on OS X
If you don't want to link against Collaboration.framework, then you can use something like CSIdentityImageGetData (or one of the similar variants) to get the image directly. I personally find working with a native Cocoa object to be nicer, but in this case it's not absolutely necessary.

Resources