iOS

iOS video guru needed

Raconteur's picture

Hi gang,

I used to be an active member here a few years ago, but have gotten sidetracked. However, I remember, back then, thinking that if there was ever a group that could help solve just about ANY programming problem, it was you all.

So, that said, I have an iOS development issue that I am hoping someone has either figured out or can at least give some ideas on.

The following is posted, verbatim, on StackOverflow, so anyone who has seen it there (no replies at all so far), sorry for the redundancy.

I am having a hell of a time with AVQueuePlayer... Very simply, I am making it on an array of AVPlayerItems built with playerItemWithURL: and pointing to video assets on a server out on the Net.

If I try to run this thing in the stimulator (sic) it plays through the first asset, begins playing the second and just dies. Sometimes it doesn't even get through the first asset.

Now, I understand that the sim behaves differently than the device, so I tried it on the device as well, with the same problem.

When I log the various status changes on the item, I see that the buffer runs out, and the player just dies. This seems a bit silly to me for a construct that is supposed to play a queue of items... of course the buffer may underrun, but why would it just die?

Am I doing something wrong, or is this how it is supposed to behave?

I have gotten around this problem by observing the loadedTimeRanges property and when it changes sending PLAY to the player. But this results in stuttering playback, which sucks too.

Here is my code. Can someone please tell me how to do this without the playback being complete crap?

- (void)viewDidLoad {
    [super viewDidLoad];
 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePlayerItemReachedEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.queuePlayer];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePlayerStalled:) name:AVPlayerItemPlaybackStalledNotification object:self.queuePlayer];
 
    NSString *baseURL = @"http://www.aDomain.com/assets/";
    NSMutableArray *vidItemArray = [[NSMutableArray alloc] initWithCapacity:5];
 
    for (int i = 1; i <= 5; i++) {
        AVPlayerItem *vid = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[baseURL stringByAppendingFormat:@"%d.mov", i]]];
        [vid addObserver:self forKeyPath:@"status" options:0 context:nil];
        [vid addObserver:self forKeyPath:@"playbackBufferEmpty" options:0 context:nil];
        [vid addObserver:self forKeyPath:@"loadedTimeRanges" options:0 context:nil];
        [vidItemArray addObject:vid];
    }
 
    self.queuePlayer = [AVQueuePlayer queuePlayerWithItems:vidItemArray];
    [self.mPlaybackView setPlayer:self.queuePlayer];
}
 
- (void)handlePlayerItemReachedEnd:(NSNotification *)notification {
    NSLog(@"Clip #%d finished playing", [self.queuePlayer.items indexOfObject:self.queuePlayer.currentItem]);
}
 
- (void)handlePlayerStalled:(NSNotification *)notification {
    NSLog(@"CLIP STALLED...");
}
 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([object isKindOfClass:[AVPlayerItem class]]) {
        AVPlayerItem *item = (AVPlayerItem *)object;
 
        if ([keyPath isEqualToString:@"status"]) {
            switch (item.status) {
                case AVPlayerItemStatusFailed:
                    NSLog(@"player item status failed");
                break;
                case AVPlayerItemStatusReadyToPlay:
                    NSLog(@"player item status is ready to play");
                [self.queuePlayer play];
                break;
                case AVPlayerItemStatusUnknown:
                    NSLog(@"player item status is unknown");
                break;
            }
        }
        else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {
            if (item.playbackBufferEmpty) {
                NSLog(@"player item playback buffer is empty");
            }
        }
        else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
            NSLog(@"Loaded time range = %@", item.loadedTimeRanges);
            self.queuePlayer play];
        }
    }
}

TouchOSC Pushbutton Sample&Hold

gtoledo3's picture

I was making a grid of buttons with TouchOSC yesterday, and wanted to set it up so that each button had a value assigned to it, and when someone pushes the button for the value to stick until they push the next button. So, if button 1 is pressed, it delivers a 1, then if button 5 is pressed it delivers a 5, for example - with only one value allowed to be generated in the button grid.

When I was looking through the options, there are pushbutton types that generate a value only when your finger is on the button, and then toggle types that you push on, then off.

The "problem" for using the toggle type for me, was that you could have multiple buttons depressed, whereas I needed the grid of buttons to only be able to deliver one output value - the last pressed.

I started fiddling around with some math patches and sample&holds, and realized I'd started recreating a part of smokris's VCR composition.

The solution is pretty simple - use the pushbuttons, and multiple each button value by the ID # that the button is supposed to have. Then, sum them all. Connect the output of the summing to the value input on a Sample & Hold. That's it! :-) I'm attaching a picture to show the setup.

AUSampler Preset Patch (Composition by dust)

Author: dust
License: (Other — see description)
Date: 2012.01.20
Compatibility: 10.7
Categories:
Required plugins:
AUSampler Plugin

here is an AUSampler plugin for QC. with apples new AUSampler component in lion.. it is now possible to quickly make software instruments by saving a preset .plist file and loading it up in your quartz or iPhone applications....

fully supported with midi io. just plug your keyboard in and launch the plugin and start playing immediately no conditional logic hassles set up or anything.

if more complex routings are more your style then you can programmatically send midi messages to the qc sampler from qc or any other host or hardware interface you have. the plugin also provides midi structured outputs messages so you have access to some raw midi note cc, and device data ;)

by using presets you can create lush multi-timbral sounds with complex parameter mapping. by sending the sampler a midi note or midi cc structure you can then gain access to performance filters and lfo's etc... it is also possible to load .dls sound fonts into the sampler editor and save them as AUSampler presets.

build some sequences in qc or add some physics to midi or maybe just add some generative soundss to your qc file.

please check the read me for the proper sample file locations.. you can load a preset from anywhere... sounds need to go in /Library/Audio/Sounds folder or the plugin Resources folder if you want to redistribute. i have included a sample preset to play with and directions on how to quickly make your own.

the plugin will not load if your presets and sounds folders are empty.

Using TUIO with more than one port

scalf's picture

I have been using the new TUIO apps for both the iOS and Android. Alone they are great, but when I connect them in combination, the one port (3333) cannot handle both at the same time.

So I am wondering if there is a way to change the port that Quartz is listening to, so you could have multiple devices connect with one application or host computer.

Since TUIO and OSC are related, I used the stock oscreceiveing patch to listen to port 3333 and the received signal would flash when the device was touched. Using the qcOSC plugin from hexler I saw that a packet was named /tuio/2Dcur, within there were 2 structures that I could get to: one was a string that said "fseq" and the other was a counter that would only increase when the pad was touched.

I then changed the Tuio settings from the device to "not send full updates" which gave me /tuio/2Dobj and /tuio/2Dbib - both of which gave nothing but a string - but still a lead.

So perhaps the source of the tuioclient plugin could be changed?

Or is there a way to dig deeper into the structure listed on the receiving OSC patch?

Thanks for any clues

http://code.google.com/p/tuiodroid/ http://code.google.com/p/tuiopad/

OpenAppMkt

gtoledo3's picture

http://www.openappmkt.com/

This may be of interest to some of you. It's basically a store that sells "web apps" for use on iOS devices.

An article that gives some background:

http://www.xconomy.com/national/2010/07/30/openappmkt-the-return-of-the-...