MPMediaItem crash on valueForProperty - mpmediaitem

I have a big problem to get the informations of the songs from the iPod library. Following the official apple reference:
MPMediaQuery *query = [MPMediaQuery songsQuery]; // query is an autorelease object
NSArray *itemsFromGenericQuery = [everything items];
for (MPMediaItem *song in itemsFromGenericQuery) {
NSString *songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
NSLog (#"%#", songTitle);
}
After some debugging I found that itemsFromGenericQuery has not nil value. The problem is that on a 3.x device with a library of about 1000 songs, spends too much memory to carry out the process and it crashes (or crashes on a single nil value). How can i fix it?

Related

In Swift, how does one assign Data to array of UInt32?

I have Swift code which reads a binary file representing a sequence of UInt32 values like this:
let fileData = binaryFile.readData(ofLength: 44)
guard fileData.count > 0 else { break }
let headerData = fileData.withUnsafeBytes {
Array(UnsafeBufferPointer<UInt32>(start: $0, count: 11))
}
let polyCount = headerData[1].bigEndian
let polyFlags = headerData[2].bigEndian
I'd not used the program containing this code for a while, but when returning to it recently, it still works as expected, but now gives a deprecation warning:
"withUnsafeBytes is deprecated: use withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R instead"
I've searched for quite a long time for an un-deprecated way to do this without success. There are many examples across the web (including in stackoverflow) but almost all of them written before this deprecation into effect. Frankly, I've fried my brain hunting and trying suggestions! I am prepared to accept that I'm missing something totally obvious ("If it's getting complicated, you're doing it wrong."), but I work in an environment where I have no colleagues to ask .. except here.
Any guidance would be much appreciated.
RamsayCons's own solution is nice, but what about the performance? I think, it could be better if we reduce all unnecessary operation.
extension Data {
func toArray<T>(type: T.Type) -> [T] where T: ExpressibleByIntegerLiteral {
Array(unsafeUninitializedCapacity: self.count/MemoryLayout<T>.stride) { (buffer, i) in
i = copyBytes(to: buffer) / MemoryLayout<T>.stride
}
}
}
measured performance gain depends, but number of execution per second is at least doubled. Bigger the data, bigger advantage!
self.dataArray = data.withUnsafeBytes{ Array($0.bindMemory(to: UInt32.self))}
Well, letting some time pass restored brain function! I found an answer (in stackoverflow, of course):
round trip Swift number types to/from Data
some way into that question/answer is:
extension Data {
func toArray<T>(type: T.Type) -> [T] where T: ExpressibleByIntegerLiteral {
var array = Array<T>(repeating: 0, count: self.count/MemoryLayout<T>.stride)
_ = array.withUnsafeMutableBytes { copyBytes(to: $0) }
return array
}
}
The trick is that Arrays are not necessarily stored in contiguous memory so simply copying enough bytes in order to the destination doesn't do it. I hope this helps the next person hunting with a fried brain!!

How to access a field in struct

I have the following code in my Xcode project:
- (BOOL)getIP;
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://httpbin.org/ip"]];
request.HTTPMethod = #"GET";
[request setValue:#"TestValue" forHTTPHeaderField:#"Test"];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"getIP returns = %#", dict);
return NO;
}
When I set a breakpoint in lldb using the "breakpoint set -b CFURLRequestSetHTTPHeaderFieldValue" command and trigger the getIP method, the code stops as expected.Then I intput the "po $x0
" lldb command and it prints "<CFMutableURLRequest 0x1741bff00 [0x1a7808bb8]> {url = http://httpbin.org/ip, cs = 0x0}".
What I want to know is: 1.how to access the url filed in struct CFMutableURLRequest; 2.how to get the definition of struct CFMutableURLRequest.
Thanks in advance!
The po command shows you the result of the description message sent to the object. There's no guarantee that the text printed by descriptionis telling you about particular ivars in the object, it's just some free-form text that the class author can fill with whatever she best thinks describes the object. The fact that it says "url =" doesn't mean there actually is an ivar called url.
You can use the p or expr commands to print the contents of the object (at least so far as that is available to the debugger.) Since this is a pointer, you'll want to do:
(lldb) p *request
In this case, it looks like these are opaque objects - the debug information doesn't say how they are laid out. So the debugger can't really help you look into the object directly.

Trouble formatting a path for the Linphone SDK in Swift

Thanks in advance for the help!
I am trying to record calls using the Linphone SDK in Swift on Mac OS, and am having trouble passing a path into the function:
func linphone_call_params_set_record_file(_ cp: OpaquePointer!, _ path: UnsafePointer<Int8>!)
that works correctly (the SDK is written in C, though I am accessing it using Swift and a bridging header). The Linphone SDK works properly, and I can make and receive calls programmatically, with full audio support.
In trying to invoke the call recorder, I pass this function a path (pathtofile), such as:
let pathtofile = "/Users/Alex/Safety/1.wav"
where I would like to store the recording file.
func SafetyNetAVRecorderInitializer(pathtofile: String) -> Bool {
// Convert pathtofile to UnsafePointer<Int8>.
let cpathtofile = (pathtofile as NSString).utf8String
let path = UnsafeMutablePointer<Int8>(mutating: cpathtofile)
// Actually begin call recording.
if currentcall != nil {
let currentcallparameters = linphone_call_get_current_params(currentcall)
linphone_call_params_set_record_file (currentcallparameters, path)
linphone_call_start_recording(currentcall)
return true
}
return false
}
No runtime errors are encountered on linphone_call_params_set_record_file(), but when I try to invoke linphone_call_start_recording(), the recording does not begin, and an error is printed in the console that reads:
ortp-error-linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file().
How can I correctly pass a valid path to linphone_call_params_set_record_file()? I have tried directly passing a plain Swift String instead of an UnsafePointer<Int8> to no avail. Am I just misunderstanding how paths are formatted in C?
For reference, the SDK method source is:
void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){
if (cp->record_file){
ms_free(cp->record_file);
cp->record_file=NULL;
}
if (path) cp->record_file=ms_strdup(path);
}
Thanks again!
Try this:
let cpathtofile = (pathtofile as NSString).utf8String! // Unwraps!
...
inphone_call_params_set_record_file(currentcallparameters, cpathtofile)

Swift "Array" memory allocation, plus toggle display mirroring

NOTE: See amended post below re: Hardware mirroring
I have written two Swift functions that toggle the display mirroring in OSX. Both work; the difference between them is just syntax when dealing with pointers. For the convenience of those interested in learning how to toggle mirroring in Swift, I have included the text of the playground file below.
My question is about memory allocation. Here is the section of interest:
toggleMirroringUgly
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
toggleMirroring
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
CGGetActiveDisplayList is a low-level function call that relies on data being arranged in consecutive memory locations. I am reasonably confident that “alloc” from the ugly version is contiguous. Empirically, it seems that the “Array(…)” call is also contiguous, but can I rely on that always being true (e.g., if the number of displays grows)? Is this assumption about the Swift array initializer poor form?
Here’s all the code; apologies for formatting issues. Note that only one of the two functions should be called; otherwise, you’ll end up where you started.
//: Playground - noun: a place where people can play
import Cocoa
// apparently not defined in Swift version of SDK 10.11 (XCode 7.3.1), so add manually
let kCGNullDirectDisplay = CGDirectDisplayID(0)
let kCGDirectMainDisplay = CGMainDisplayID() // not used here, just for the record
let maxDisplays:UInt32 = 20 // not used
var onlineCount:UInt32 = 0 // not used
func postError(error : CGError){
if error != CGError.Success {
print("got an error")
}
}
// this toggles all active displays, online or not
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
//***
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
//***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef = nil //swift 3 syntax
postError(CGBeginDisplayConfiguration(&configRef));
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master);
}
}
if (false){ // change to true in order to execute the toggle
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.Permanently))
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
func toggleMirroringUgly(){
// just to decrease eye strain
typealias displayIDListPtr = UnsafeMutablePointer<CGDirectDisplayID>
typealias configurationRefPtr = UnsafeMutablePointer<CGDisplayConfigRef>
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
// ***
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
// ***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// make room for the configuration reference
let configRefPtr = configurationRefPtr.alloc(1) //see typealias above
// start the configuration
postError(CGBeginDisplayConfiguration (configRefPtr));
for i in 0..<displayCount {
let currentDisplay = CGDirectDisplayID(displayListPtr[Int(i)])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRefPtr[0], currentDisplay, master);
}
}
if (false){ //change to true in order to flip the mirroring
// make it happen
postError(CGCompleteDisplayConfiguration (configRefPtr[0],CGConfigureOption.Permanently));
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
toggleMirroring()
Arrays don't necessarily use contiguous storage. There is a ContiguousArray type which you can use if you are so inclined, but you'll still need to deal with the possible difference between your maximum size and the actual size returned after the final call to CGGetActiveDisplayList.
One way of cleaning this up might be to make a custom convenience initializer for Array:
extension Array {
init<Size: IntegerType>(
fillingBufferOfSize maxSize: Size,
#noescape fillBuffer: (buffer: UnsafeMutablePointer<Element>, count: inout Size) throws -> ()) rethrows
{
let maxSizeAsInt = Int(maxSize.toIntMax())
let buf = UnsafeMutablePointer<Element>.alloc(maxSizeAsInt)
defer { buf.dealloc(maxSizeAsInt) }
var actualCount: Size = 0
try fillBuffer(buffer: buf, count: &actualCount)
self.init(UnsafeBufferPointer(start: buf, count: Int(actualCount.toIntMax())))
}
}
Then you can use Array(fillingBufferOfSize: ...):
var maxActive: UInt32 = 0
CGGetActiveDisplayList(0, nil, &maxActive)
let displays = Array(fillingBufferOfSize: maxActive) { (buffer, count) in
CGGetActiveDisplayList(maxActive, buffer, &count)
}
I upgraded my computer with a new video card and NVIDIA drivers and discovered my code above no longer works fully - turns mirroring on but not off. Apparently, there's an option for drivers to use hardware or software mirroring, and that changes the coding. I post below a revised version.
It has only been tested on my system (10.12.2) and card (GTX 980Ti), but I think the logic should accommodate software mirroring and fairly recent OS versions as well. If you have more than 2 displays, you can probably modify it, with heroic effort, to mirror arbitrary combinations. My code will just mirror whatever is considered the main display (or the lowest rez one, in software mirroring) on all the others.
Although jbandes' note re: ContiguousArray was informative, it does not work in this case - see the comments in the code. This code assumes that the allocated array of UInt32s will be contiguous. (Too much work to get fancy with malloc and casting, but this is not production ready.)
Good luck to the 2 people who might be interested!
//: Playground - noun: a place where people can play
import Cocoa
import Foundation
func postError(_ error : CGError){
if error != CGError.success {
print("got an error")
}
}
func disableHardwareMirroring(){
// designed for hardware mirroring with > 1 display
// should be no penalty for running with only 1 display, using either hardware or software mirroring drivers
// but not tested
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
// only interested in the main display
// kCGNullDirectDisplay parameter disables hardware mirroring
CGConfigureDisplayMirrorOfDisplay(configRef, CGMainDisplayID(), kCGNullDirectDisplay)
// may not be permanent between boots using Playgroud, but is in an application
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
}
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0 //used as a parameter, but value is ignored
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount == 1 {
// either it's hardware mirroring or who cares?
disableHardwareMirroring()
return
}
// allocate space for list of displays
// tried to use ContiguousArray, but CGGetActiveDisplayList requires Array<CGDirectDisplayID> parameter
// ContiguousArrays cannot be typecast to Arrays (at least not easily)
var displayIDList = Array<CGDirectDisplayID>(repeating: kCGNullDirectDisplay, count: Int(displayCount))
// fill the list
postError(CGGetActiveDisplayList(displayCount, &(displayIDList), &activeCount))
// determine if mirroring is active (only relevant for software mirroring)
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master)
}
}
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
if (false) { // change to true to run the code, false to edit
toggleMirroring()
}

copy NSData to UnsafeMutablePointer<Void>

Hi there stackoverflowers. I'm implementing a wrapper for Secure Transport and I'm stuck on some of the C -> Swift syntax.
func sslReadCallback(connection: SSLConnectionRef,
data: UnsafeMutablePointer<Void>,
var dataLength: UnsafeMutablePointer<Int>) -> OSStatus
{
//let bytesRequested = dataLength.memory
let transportWrapper:SecureTransportWrapper = UnsafePointer(connection).memory
let bytesRead:NSData = transportWrapper.readFromConnectionFunc(transportWrapper.connection)
dataLength = UnsafeMutablePointer<Int>.alloc(1)
dataLength.initialize(bytesRead.length)
if (bytesRead.length == 0)
{
return OSStatus(errSSLClosedGraceful)
}
else
{
data.alloc(sizeof(bytesRead.length)) //<----compile error here
return noErr
}
}
I've marked the location of the compile error. I don't blame it for erring, I was kind of guessing here :P. I'm trying to copy the the NSData to the data:UnsafeMutablePointer. How do I do that?
Compile error:
/Users/*/SecureTransportWrapper.swift:108:9: Static member 'alloc' cannot be used on instance of type 'UnsafeMutablePointer' (aka 'UnsafeMutablePointer<()>')
Thanks a ton!
================
Update: here is the api doc for what the sslReadCallback is supposed to do:
connection: A connection reference.
data: On return, your callback should overwrite the memory at this location with the data read from the connection.
dataLength: On input, a pointer to an integer
representing the length of the data in bytes. On return, your callback
should overwrite that integer with the number of bytes actually
transferred.
Excerpt from here
OK, lets go through your code:
dataLength = UnsafeMutablePointer<Int>.alloc(1)
dataLength.initialize(bytesRead.length)
dataLength is a pointer you get passed in, it is where the caller of the function both gives you the size of the buffer and wants you to put the number of bytes you read. You don't need to alloc this, it is already allocated.
(Irrelevant for this example but: Also in alloc(N) and initialize(N) the N should be the same (it is the amount of memory being allocated, and then initialized))
I think what you want (Swift 3 uses pointee instead of memory) is this:
dataLength.memory = bytesRead.length
The C API says that you also get the size of the data buffer from this variable. data will be pre-allocated for this size.
Make sure the data you read fits (bytesRead.length <= dataLength.memory), then just do a
memcpy(data, bytesRead.bytes, bytesRead.length)
That's all.

Resources