Cannot play album with AVAudioPlayer - macos

I'm working on a very simple OSX application that will allow me to play either a song or a folder of songs.
I can choose a song and play it and everything is fine. I can choose a folder and create an array of songs and... play the last one.
var currentSong: NSURL?
var album: [NSURL] = []
var audioPlayer = AVAudioPlayer()
My playing function is
func playCurrent(){
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: currentSong!)
} catch {
print("Ignoring errors for now")
}
audioPlayer.play()
}
This works fine whenever I set currentSong to a NSURL. I choose one song, it plays it.
My album function is as follows:
#IBAction func chooseAlbumAndPlay(sender: AnyObject) {
album = albumFromFile()
for song in album {
currentSong = song
playCurrent()
}
}
and here I have the problem. albumFromFile opens an NSOpenPanel, lets me choose a folder, and dumps paths to playable items into an array of NSURLs. This part works, I've verified it, so I really have an array with 12 or 20 or whatever correct, playable URLs. If I just run it as is, only the last song in any album gets played. If I set a breakpoint in the playCurrent() function, I can hear that it will actually play a tiny snippet - less than a note in most cases - of all songs but the last.
According to the documentation, play() returns a boolean - and it will happily report that it has finished playing every song in this loop.
My - human - opinion is that a song has only finished playing when I have heard all of it.
If I query the duration of the current AVAudioPlayer, they all report perfectly reasonable-sounding values.
I'm completely stumped here. PlayCurrent seems to completely fail to assert itself as a running function. The expected behaviour is that it will not exit until play() has finished playing; observed behaviour is that it will touch every song for the briefest time, go 'been there' and return to the enclosing loop.
How can I force AVAudioPlayer to play the whole of a file before exiting my playCurrent() function? And where would I have found that information? (The class documentation is unhelpful, the mentioned audio guides do not exist - right now, the Developer Library does not mention any basic audio guides for OSX.

The answer is, once you get around to it, very obvious indeed. Unfortunately, the documentation really is no help at all. I could, in theory, have found the solution by looking at the entry for AVAudioPlayer in the AVFoundationFramework reference, but I didn't. (I found it by wildly casting about and a chance mention).
There appear to be no working OSX examples; Apple's iOS example uses the MediaPlayer framework that is not available on OSX.
The solution is as follows:
An AVAudioPlayer plays a single sound.
If you want to play more than one sound, you need an AVQueuePlayer which can also play a single sound from a URL or a queue of AVPlayerItems (this class has an init(URL:) method).
If anyone has an idea why AVAudioPlayer behaves as it does, I'm still interested to hear it.

Related

How to get a death animation for my character in ActionScript 3 (Adobe Animate)

So basically I have two questions. I am also copying off this video from 2014: https://www.youtube.com/watch?v=w8JgpEjm8i8&t=2792s
Question 1
At the end of the video above the guys computer completely crashed and he wasnt able to show the end of how to setup a death animation for my player (link). So currently I have setup a movie clip of the death animation - just the playing spinning around - and put it in another movie clip called 'All Sprites' in which I have my other movie clips such as the different walking directions. So I have placed it in there, labelled it with "Link Death Frame". I then went back to the main script and added code so that once my player dies, the animation will play. Such as:
~
if(linkHealthBarMC.scaleX <= 0.01)
{
linkAlive = false;
}
trace(linkAlive);
if(linkAlive == false)
{
linkMC.gotoAndStop("Link Death Frame");
}
~
However, the issue comes in which the animation doesnt actually play, it just goes straight to the first frame and doesnt play. I have tested it and I know for sure that it gets stuck on the first frame and that something must be wrong with the animation as I tested it with another animation and it worked fine (once I met the requirements for the animation to play). So does anyone have any idea how I can fix this issue so that my character can play a death animation?
Question 2
How do I stop time? Like just completely freeze everything after my character is dead? Because at the moment I am just going to the first frame of the death animation and can still move and attack.
I'd assume this is on an EnterFrame loop. Then you would have two possible causes for this:
1.) You're loop is constantly checking if the 'linkAlive' if statement is false (which it is) and setting your Animation to the first frame. You can check this method by putting a Trace statement in your if statement and if the output window overflows, then that's your culprit.
2.) What you want is gotoAndPlay(-insert label here-)
Tho it is outside the scope of the question you have, I create a variable~Switch State machine to control states for me:
1.) Current State as a number (int, number, or uint)
2.) function with a switch statement (Switch is kind of a fancy if Statement)
3.) inside the cases are instructions
switch(current_state){
case 1:
linkMC.gotoAndPlay('death animation');
break;
}
if (current_state != 1){
-put movement code here-
}
This is close to what I use for my game. Just checking states or you can have a variable like the one above that explicitly checks for the death state and remove the ability to move. If you use a mouse (and I assume event listener) then you can remove the event listener for the mouse. If you use a solution like keyboard inputs then an if statement would be more what you are looking for.

Unity, character selection screen on same PC by two players

The game I am trying to make include local multiplayer to play on same PC. I have done by making the different controllers in input manager and game work perfectly fine.
But now I am onto the part where I have to create a character selection screen for multiple player on same PC. I am beginner to the unity and learning right now. So I have no idea how to make it happen. Because when I tried to make it unity UI didn't able to take two input. At a time
I have also watched some of the threads in which people suggested to make your own eventsystem and button but I tried doing that somehow buttons are not taking any response they are not clickable. If anyone has seen those thread and that method is working for them, so please let me know how to.make it work
Or if someone has any other idea how to do please let me know
Thanks in advance
As far as I know, you CAN'T have more than one event system in the same scene.
So knowing that I'll suggest to change the...perspective about your game, here is something that can work:
You can't have more than one input on the same UI, but you can distinguish "keyboard" inputs. So let's guess the scenario that you have the screen divided in 2 parts, where left side is the Player 1 selection character, and can select between 2 characters, and right side is the Player 2 selection character, with the same number (or different, as you want!) of possible characters.
The pseudo code will be something like:
private Player m_player1;
private Player m_player2;
private CharacterSelection m_CharacterSelection_Player1;
private CharacterSelection m_CharacterSelection_Player2;
If (m_Player1.Input.GetKeyDown(KeyCode.A))
{
m_CharacterSelection_Player1.Left();
}
else if(m_Player1.Input.GetKeyDown(KeyCode.D)){
m_CharacterSelection_Player1.Right();
}
If (m_Player2.Input.GetKeyDown(KeyCode.LeftArrow))
{
m_CharacterSelection_Player2.Left();
}
else if(m_Player1.Input.GetKeyDown(KeyCode.RightArrow)){
m_CharacterSelection_Player2.Right();
}
Here is the visual representation about what I'm trying to tell you:

ncmpcpp stops highlighting current song

Hi I'm recently working around with ncmpcpp and I've configured it pretty nicely to what I want. Unfortunately on playlist view, after 3-4 seconds it will stop highlighting the currently played song, and as a result I lose track of where I am in my playlist (even though the song is played in the header).
Is there a way to have the currently played song constantly highlighted? I've looked through the numerous ncmpcpp config options and I couldn't find something to this.
Here's a gif of what is happening:
http://i.imgur.com/9eCOLyj.gif
Here is the config file for ncmpcpp: http://pastebin.com/XTdQa2qb
Here is the config file for mpd:
music_directory "~/Music/albums"
playlist_directory "~/.mpd/playlists"
db_file "~/.mpd/mpd.db"
log_file "~/.mpd/mpd.log"
pid_file "~/.mpd/mpd.pid"
state_file "~/.mpd/mpdstate"
auto_update "yes"
auto_update_depth "2"
audio_output {
type "osx"
name "aMat Mac Device"
mixer_type "software"
}
audio_output {
type "fifo"
name "my_fifo"
path "/tmp/mpd.fifo"
format "44100:16:2"
}
bind_to_address "localhost"
Well lesson learned, always read the man page!
There's a ncmpcpp config option playlist_disable_highlight_delay = 0 which solves the issue of the highlighting fading away. When you set it to 0 it will stay highlighted forever.
Although what would be ideal would be if I could highlight other parts of my playlist and still have some indicator on what is currently playing. But c'est la vie, this is a solution.

How can I be notified that a movie has been determined not to be a movie?

I'm writing a Mac app that plays MPEG-4 movies using AVPlayer.
My app supports both local movies and movies from the internet, via an “Open Location” dialog. In the latter case, when the user enters a URL and presses the OK button, my app opens the URL as a document.
Local files are easy—Launch Services will tell Finder, Dock, etc. not to light my app up for any local file that isn't a .mp4 or similar. If the user forces my app to open some random file (e.g., by holding down ⌘ when dragging it onto my app), that's their own fault.
Non-local (e.g., internet) URLs are the problem. If I supply a URL that doesn't lead to an MPEG-4, I need to show an alert and close the document.
Of course, I'm not downloading the URL myself; I just hand it to AVPlayer.
So I need a way to be notified by my AVPlayer that what I've given it is not a movie.
I've tried observing the player's status. That gets set to AVPlayerStatusReadyToPlay.
I've tried observing the player's currentItem's tracks. At least on Lion, for an invalid movie, the item's tracks never changes. (This stands to reason—the only reason it would change would be tracks coming in, which is, by definition, impossible for a non-movie.)
I can't just check tracks when status changes, because that may not be set yet (on Mavericks, status changes before tracks).
So, how can I be notified by my AVPlayer that it has conclusively determined that what the URL refers to is not anything it can play?
It's absolutely not definitive, but in my experience, when the player's status becomes AVPlayerStatusReadyToPlay, you can inspect the playable property of asset of the player's currentItem. If playable is YES, you can assume the URL led to a viable MP4. If not, you can assume it did not.
- (void) observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context
{
if( [keyPath isEqualToString:#"status"] ) {
if( self.player.status == AVPlayerStatusReadyToPlay &&
self.player.currentItem.asset.playable ) {
[self.playerView.player play];
}
else {
// TODO: show an error dialog here.
[self.window close];
}
}
}
I've code similar to the above in one of my apps, and it seems to work as expected in every case I've tried. I can whip up a test app with it if you like.

Correct way to drive Main Loop in Cocoa

I'm writing a game that currently runs in both Windows and Mac OS X. My main game loop looks like this:
while(running)
{
ProcessOSMessages(); // Using Peek/Translate message in Win32
// and nextEventMatchingMask in Cocoa
GameUpdate();
GameRender();
}
Thats obviously simplified a bit, but thats the gist of it. In Windows where I have full control over the application, it works great. Unfortunately Apple has their own way of doing things in Cocoa apps.
When I first tried to implement my main loop in Cocoa, I couldn't figure out where to put it so I created my own NSApplication per this post. I threw my GameFrame() right in my run function and everything worked correctly.
However, I don't feel like its the "right" way to do it. I would like to play nicely within Apple's ecosystem rather than trying to hack a solution that works.
This article from apple describes the old way to do it, with an NSTimer, and the "new" way to do it using CVDisplayLink. I've hooked up the CVDisplayLink version, but it just feels....odd. I don't like the idea of my game being driven by the display rather than the other way around.
Are my only two options to use a CVDisplayLink or overwrite my own NSApplication? Neither one of those solutions feels quite right.
I am curious to see if anyone who has actually done this cares to weigh in, but here is my understanding:
Apple pushes the CVDisplayLink solution over doing a loop on the main thread that uses -nextEventMatchingMask:untilDate:inMode:dequeue: because, I think, it provides better responsiveness for UI controls. This may not be relevant for full-screen games. (Note: You don't need to replace NSApplication to use that form of game loop.) I think the main potential issue with using CVDisplayLink is that it will only run one frame in advance and it does this determination early, which is even stronger than vertical sync. On the plus side, it might improve latency.
Other solutions include decoupling rendering from game logic and running game logic periodically on the main thread and rendering on the CVDisplayLink thread. I would probably only recommend this, however, if you run into issues with the game-driven-by-display paradigm.
You don't necessarily have to make your own NSApplication based class or use CVDisplayLink to get around the fact that an app's runloop is hidden from you in Cocoa.
You could just create a thread and have your run loop in there instead.
For what it's worth though, I just use CVDisplayLink.
I'm sticking something up here to revive this question...mainly out of portability. I found from studying the OLC Pixel Game Engine, that it works with a do{}while loop and std::chrono to check the timing of the frame to calculate fElapsed Time. Below is some code I wrote to do the same thing. It also adds a makeup portion, to govern the framerate from shooting above a certain value, in this case, 60 FPS.
c++ code
int maxSpeedMicros = 16700;
float fTimingBelt; //used to calculate fElapsedTime for internal calls.
std::chrono::steady_clock::time_point timingBelt[2];
bool engineRunning = false; //always have it true, until the engine stops.
bool isPaused = false;
do {
timingBelt[1] = std::chrono::steady_clock::now();
fTimingBelt = std::chrono::duration_cast<std::chrono::microseconds>(timingBelt[1] - timingBelt[0]).count() * 0.000001;
if (isPaused) {
do {
std::this_thread::sleep_for (std::chrono::milliseconds(100));
timingBelt[1] = std::chrono::steady_clock::now();
} while (isPaused);
}
timingBelt[0] = std::chrono::steady_clock::now();
// do updating stuff here.
timingBelt[1] = std::chrono::steady_clock::now();
int frameMakeup = std::chrono::duration_cast<std::chrono::microseconds>(timingBelt[1] - timingBelt[0]).count();
if (frameMakeup < maxSpeedMicros) {
int micros = maxSpeedMicros - frameMakeup;
std::this_thread::sleep_for (std::chrono::microseconds(micros));
}
} while (engineRunning);
However, that code was in direct conflict with Cocoa's event driven model.
Custom main application loop in cocoa
So as a bandaid, I commented out the whole loop, and created a new method that runs one iteration of the loop. I then implemented this in my AppDelegate:
Objective C Code
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
engine->resetTimer();
[NSTimer scheduledTimerWithTimeInterval:0.016666666667 target:self selector:#selector(engineLoop) userInfo:nil repeats:YES];
}
-(void) engineLoop { //Let's handle this by the engine object. That's too complicated!
engine->updateState();
[glView update]; //Since the engine is doing all of its drawing to a GLView
[[glView openGLContext] flushBuffer];
}
Still to do is adjust the tolerance of the timer object. Apple Developer documentation states that if a timer object misses the next window, it will wait for the next frame time. However, a tolerance allows it to shift the timing of future events to make smoother framerate transitions and better use of CPU power.
So at this point I am open to suggestions and input about what others have done to make more portable code. I am planning on a boolean argument in the constructor of the engine named "eventDriven" and if false, will start its own game loop thread, then split out the top event loop to call an "engineUpdate" method that handles all of the code that can be event driven. Then in the case of building on an event driven system, the delegate can just construct the engine with a engineUpdate = TRUE and have their events drive the gameUpdate.
Has anyone done this? and if so, how does it perform cross platform?

Resources