AVAudioPlayer stops - avaudioplayer

I'm trying to play a mp3 file with using AVAudioPlayer:
NSString *path = NSString stringWithFormat:#"%#/%#" ,
[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSURL* url = [NSURL fileURLWithPath:path];
AVAudioPlayer* player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
[player play];
NSLog(#"%f/%f", player.currentTime, player.duration);
However, the player stops around 478.558367 every time even though its duration is 1044.437506.
Why does the player stop in the middle of the track?

Related

Having trouble in converting data into NSString from NSData

I want to convert NSData into NSString, my code is below.
NSData *data1 = [object valueForKey:#"college_list"];
NSString *myString =[ NSString stringWithCString:[data1 bytes] encoding:NSUTF8StringEncoding];
What is wrong with this code?
If 'data1' do have some thing in it. Try this:
[[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding]
May be there is some this wrong with your 'object'. Check its data is valid or issue is in its data.

NSURLResponse Content-Length mismatch size of actual data when running concurrent downloads

I have a UITableView, when a cell is selected, I make a service call to asynchronously download a PDF file from a web service. It works great, until you select multiple cells directly after one-another (individually), then things start going south..
Here's some (stripped down) code to clarify:
Inside MasterViewController.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//To uniquely identify this field, I build a simple string using the indexPath.
NSString *key = [[NSString alloc]initWithFormat:#"%d.%d",pIndex.section,pIndex.row];
//Use a pre-populated NSDictionary to specify the file I want from the server.
NSString *reportID = [reportDictionary valueForKey:key];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/RequestReportWithID",myConnectionObject.ServiceURL]];
NSMutableDictionary *body = [[NSMutableDictionary alloc] initWithObjectsAndKeys:reportID, #"reportID", nil];
NSData *requestData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody: requestData];
//Create a new object as delegate to receive the data, also add the key to assist with identification.
ReportDownloader *newReportDownloader = [[ReportDownloader alloc]initWithDelegate:self andKey:key];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:newReportDownloader];
if (connection)
{
//Nothing to do here, request was made.
}
}
Inside ReportDownloader.m:
long long expectedReportSize;
NSString *key;
NSData *thisReport;
-(NSObject*)initWithDelegate:(NSObject*)pDelegate andKey:(NSString*)pKey
{
myTypedDelegate = (MasterViewController*)pDelegate;
Key = pKey;
return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
expectedReportSize = [response expectedContentLength];
NSLog(#"Key:%#, Expected Size=%lld bytes",Key, [response expectedContentLength]);
thisReport = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[thisReport appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Here is where things go wrong...
NSLog(#"Key:%#, Actual Size=%ld bytes",Key, (unsigned long)[thisReport length]);
}
The above code works fine for a single report. And on a fast line, it works fine for 3-4 reports, but try to do more than that and the Expected length starts mismatching the Actual length. And I can't understand whyyyyy....
See the output generated by the code above:
(Notice that only the report for indexPath 1.1 was downloaded correctly)
Key:1.0, Expected Size=304006 bytes
Key:1.3, Expected Size=124922 bytes
Key:1.0, Actual Size=369494 bytes
Key:1.3, Actual Size=380030 bytes
Key:1.2, Expected Size=179840 bytes
Key:1.4, Expected Size=377046 bytes
Key:1.2, Actual Size=114376 bytes
Key:1.5, Expected Size=175633 bytes
Key:1.4, Actual Size=180558 bytes
Key:1.5, Actual Size=274549 bytes
Key:1.1, Expected Size=443135 bytes
Key:1.1, Actual Size=443135 bytes
The data corruption is confirmed when trying to open the PDF documents, which fail for all file's who's data size didn't match the expectedContentLength.
I am completely baffled by this behaviour, I'm hoping that I'm making an obvious n00b mistake and that someone here spots it.
The main reason WHY I made the ReportDownloader class was to avoid problems like this one.
Thanks in advance to whoever takes the time to scan my code!
Ok, the solution to this problem can be found here:
https://stackoverflow.com/a/1938395/1014983
This answer by James Wald, although not the question's accepted answer, completely solved all my problems with multiple simultaneous async NSURLConnections.
Let me know if you need some help with the implementation, but it's pretty straight forward.

Binary representation of NSString

I need to someone to send me binary data via NSStream and I will convert it into NSString on my end. What's the binary representation that they need to know (byte size, byte order) in order for me to convert the data successfully back into the same string in NSString?
First get the data and convert it into NSData
Then convert NSData to NSString
NSString* newStr = [[[NSString alloc] initWithData:theData
encoding:NSUTF8StringEncoding] autorelease];
If the data is null-terminated, you should instead use -stringWithUTF8String: to avoid the extra \0 at the end.
NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];
(If you have ARC enabled, remove the -autorelease call.)

Receiving Corrupted Info From Server

On Iphone as well as android I am getting response codes of 200 meaning that I am getting a valid and good response with no errors, but the json that I am receiving has additional characters. I print out the NSData that I receive and it is 580 in length and the NSString, at least when it fails, will have a larger length and print n+ extra characters on the end of the json. I am not sure why this would be but thought I would see if anyone can see what I would be doing incorrectly.
NSString *post = [NSString stringWithFormat:#"referer=%#&username=%#&password=%#", referer, username, password];
NSData *pData = [post dataUsingEncoding: NSUTF8StringEncoding allowLossyConversion:YES];
NSString *pLength = [NSString stringWithFormat:#"%d", [pData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
[request setURL:self.url];
[request setHTTPMethod:#"POST"];
[request setValue:pLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:pData];
[request setTimeoutInterval:30];
NSHTTPURLResponse *response = nil;
NSError *err = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSString *sData = [NSString stringWithUTF8String:[data bytes]];
I do not receive any errors and every response code that I receive is 200. I have printed out all of these values as well. data length is 580 and sData will vary at times but when it does pass it will be 580 in length, but this can change for different cases. The data will not always be 580 for other users that use the system.
ANSWER:
I solved the problem instead of using
NSString *sData = [NSString stringWithUTF8String:[data bytes]];
You should use
NSString *sData = [[NSString alloc] initWithData: data encoding: NSUTF8String];
This will alloc the correct amount of space based on the NSData object and thus the NSString will never try to access or store more space in that may be behind the last address that should have been accessed.
ANSWER:
I solved the problem instead of using
NSString *sData = [NSString stringWithUTF8String:[data bytes]];
You should use
NSString *sData = [[NSString alloc] initWithData: data encoding: NSUTF8String];
This will alloc the correct amount of space based on the NSData object and thus the NSString will never try to access or store more space in that may be behind the last address that should have been accessed.

Using AVAudioPlayer in iOS5?

So I'm trying to play a .wave file in iOS5, and I'm getting a warning, which is leading to SIGABRTs and generally not-working code.
NSURL *soundUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/Resources/Sounds/01_main_menu_list.wav", [[NSBundle mainBundle] resourcePath]]];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
[_audioPlayer setDelegate:self];
[_audioPlayer play];
This is giving me an error "Sending "ViewController *const __strong" to parameter of incompatible type 'id '.
I have literally no idea why, I've followed a half-dozen examples and am coming up empty. I'd love a pointer in the right direction.
This should work:
NSURL* soundUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"01_main_menu_list" ofType:#"wav"]];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
audioPlayer.delegate = self;
[audioPlayer play];
If not, I think there's something wrong with the wav file. Maybe the encoding?
Turned out it was an issue with ARC releasing, I fixed it by adding a #property and #synthesize pair for the AVAudioPlayer in question, and declaring it as strong. It got rid of all of these errors, and played the file with no problems.

Resources