API call help

Mac OSX specific forum
spacebuddy
Enthusiast
Enthusiast
Posts: 356
Joined: Thu Jul 02, 2009 5:42 am

API call help

Post by spacebuddy »

I am trying to call an API (NSOpenPanel) but running into problems.

I want to replace OpenFileRequester with NSOPenPanel. Any API gurus here :D
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: API call help

Post by Fred »

Unfortunately, NSOPenPanel is Cocoa (objectiveC) and this is not accessible trough PB. The 'easier' is your really need it is to write a small wrapper in ObjectiveC which expose a C function and then call it from PB
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: API call help

Post by wilbert »

Fred is right, it's Cocoa.
Last edited by wilbert on Sun Sep 23, 2012 12:07 pm, edited 1 time in total.
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: API call help

Post by Polo »

By the way... ;)

How would you convert a PB string to a NSString?

This is what I do:

Code: Select all

void function (const char* pbstring)
{
NSString string = [NSString stringWithUTF8String: string];
}
When PB is in non unicode mode, it works if there aren't any special character in the PB String (ie éèë...)
When PB is in unicode mode, it only gets the first letter of the PB string into the NSString.

Any solution? :)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: API call help

Post by wilbert »

Polo wrote:How would you convert a PB string to a NSString?
It's easier to use

NSString * string = [NSString stringWithFormat:@"%S", pbstring];

when unicode is used and

NSString * string = [NSString stringWithFormat:@"%s", pbstring];

when unicode is not used. That way you can use a static variable you set once that contains the format ( @"%S" or @"%s" ) and use the same convert function all the time.
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: API call help

Post by Polo »

Using Cocoa panels in PB, that's quite easy, just link your app with cocoa

ImportC "/System/Library/Frameworks/Cocoa.framework/Cocoa"
EndImport
ImportC "/System/Library/Frameworks/AppKit.framework/AppKit"
EndImport

(last one is just in case :) )

Create a static library with Xcode with the ObjC code you need, like this for instance, and import the C function in PB.
(you'd still need to handle the string conversion to make the panel customisable, which i didn't in the example below)

Code: Select all

void mOpenFileRequester()
{
NSString *title = "Requester title";
NSString *directory = "";
NSString *file = "";
NSString *extensions = "";

currentwin=[NSApp keyWindow];
if ( !currentwin ) [NSApp activateIgnoringOtherApps:YES];
    
NSOpenPanel *panel=[NSOpenPanel openPanel];
[panel setTitle:title];
		
if ( [panel runModalForDirectory:directory file:file types:extensions]==NSFileHandlingPanelOKButton )
{
  NSString *fileselected=[[panel filename] UTF8String];
}
	
if ( currentwin ) [currentwin makeKeyWindow];
}
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: API call help

Post by Polo »

Cheers wilbert, works great!
Khorus
User
User
Posts: 25
Joined: Sat Nov 13, 2010 11:22 pm

Re: API call help

Post by Khorus »

I'd like to do the same (calling a Cocoa API). I need to access CoreMIDI to do some real-time MIDI. I used the WinAPI on Windows but it looks like a different game on MacOS X. Thanks!
Wolfram
Enthusiast
Enthusiast
Posts: 604
Joined: Thu May 30, 2013 4:39 pm

Re: API call help

Post by Wolfram »

Hi,

can some give me a easy example of this code. I'm a beginner and have no experience with C.

Thanks!
macOS Catalina 10.15.7
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: API call help

Post by wilbert »

Wolfram wrote:can some give me a easy example of this code. I'm a beginner and have no experience with C.
I'm not sure what your goal is.
Polo gave a small piece of Objective-C code a few posts above if that's what you are looking for.

When it comes to the question this thread started with, it's no longer relevant. At that time, PureBasic for OS X was Carbon based.
The current 5.2x LTS version is Cocoa based and allows you to interact using the CocoaMessage() command.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: API call help

Post by Danilo »

Wolfram wrote:can some give me a easy example of this code. I'm a beginner and have no experience with C.
PB help says:
Note: The 'Pattern$' and 'PatternPosition' parameters have no effect on Mac OSX (the requester always displays all files).
So here a version with patterns, based on Polo's Objective-C code:

Code: Select all

Macro CreateCocoaObject(objectName,withMethod="alloc")
    CocoaMessage(0,0,objectName+" "+withMethod)
EndMacro


#showHiddenFiles        = 1
#allowMultipleSelection = 1 << 1
#returnAbsoluteNames    = 1 << 2

#NSFileHandlingPanelOKButton     = 1
#NSFileHandlingPanelCancelButton = 0

Procedure OpenFileRequester_(List out.s(), title.s, defaultdirectory.s="", pattern.s="", message.s="", flags=0)
    ClearList(out())
    NSApp = CreateCocoaObject("NSApplication")
    If NSApp
        currentwin = CocoaMessage(0,NSApp,"keyWindow")
        If Not currentwin
            CocoaMessage(0,NSApp,"activateIgnoringOtherApps:",#YES)
        EndIf
        
        panel = CreateCocoaObject("NSOpenPanel","openPanel")
        If panel
            ;
            ; set title
            ;
            CocoaMessage(0,panel,"setTitle:$",@title)
            
            ;
            ; set optional message text
            ;
            If message
                CocoaMessage(0,panel,"setMessage:$",@message)
            EndIf
            
            ;
            ; set allowed patterns, separated by '|'
            ;
            If pattern <> ""
                i = 1
                nextPattern.s = StringField(pattern,i,"|")
                fileTypesArray = CocoaMessage(0,0,"NSArray arrayWithObject:$", @nextPattern)
                Repeat
                    i + 1
                    nextPattern = StringField(pattern,i,"|")
                    If nextPattern
                        fileTypesArray = CocoaMessage(0,fileTypesArray, "arrayByAddingObject:$", @nextPattern)
                    EndIf
                Until nextPattern = ""
                CocoaMessage(0,panel,"setAllowedFileTypes:",fileTypesArray)
            EndIf
            
            ;
            ; show hidden files?
            ;
            If flags & #showHiddenFiles
                CocoaMessage(0,panel,"setShowsHiddenFiles:",#YES)
            EndIf
            
            ;
            ; allow multiple selection?
            ;
            If flags & #allowMultipleSelection
                CocoaMessage(0,panel,"setAllowsMultipleSelection:",#YES)
            EndIf
            
            ;
            ; set default directory
            ;
            url = CocoaMessage(0,0,"NSURL URLWithString:$",@defaultdirectory)
            CocoaMessage(0,panel,"setDirectoryURL:",url)
            
            ;
            ; run
            ;
            If CocoaMessage(0,panel,"runModal") = #NSFileHandlingPanelOKButton
            
                ;
                ; get results
                ;
                results = CocoaMessage(0,panel,"URLs")
                If results
                    count = CocoaMessage(0, results, "count")
                    If count
                        For i = 0 To count-1
                            NSURL = CocoaMessage(0,results,"objectAtIndex:",i)
                            If NSURL
                                If Not flags & #returnAbsoluteNames
                                    ;
                                    ; return file names
                                    ;
                                    string = CocoaMessage(0,NSURL,"fileSystemRepresentation")
                                    If string
                                        fileName.s = PeekS(string,-1,#PB_UTF8)
                                        If AddElement(out())
                                            out() = fileName
                                        EndIf
                                    EndIf
                                Else
                                    ;
                                    ; return absolute names
                                    ;
                                    string = CocoaMessage(0,NSURL,"absoluteString")
                                    If string
                                        utf8 = CocoaMessage(0,string,"UTF8String")
                                        If utf8
                                            fileName.s = PeekS(utf8,-1,#PB_UTF8)
                                            If AddElement(out())
                                                out() = fileName
                                            EndIf
                                        EndIf
                                    EndIf
                                EndIf
                            EndIf
                        Next i
                    EndIf
                EndIf
            EndIf
        EndIf
    EndIf
    If currentwin
        CocoaMessage(0,currentwin,"makeKeyWindow")
    EndIf
    ProcedureReturn count
EndProcedure




NewList files.s()

num = OpenFileRequester_( files(),
                          "Please choose file(s) to load",
                          "/users/",
                          "pb|pbi|prefs|rtf|txt",
                          "Optional message:"+#CR$+"Please open a file for loading."+#CR$+"Second message line",
                          #allowMultipleSelection |
                          #showHiddenFiles )

Debug num

ForEach files()
    Debug files()
Next
Polo's example used "runModalForDirectory:file:types:" method, and it was marked deprecated in OS X v10.6.
My version uses newer methods, but I think it requires at least OS X v10.6.
Wolfram
Enthusiast
Enthusiast
Posts: 604
Joined: Thu May 30, 2013 4:39 pm

Re: API call help

Post by Wolfram »

Many Thanks!

but I get an Error if I try to load a File
Object dose not respond to method "fileSystemRepresentation"
macOS Catalina 10.15.7
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: API call help

Post by wilbert »

Wolfram wrote:Object dose not respond to method "fileSystemRepresentation"
The fileSystemRepresentation method requires OS X 10.9 (Mavericks).
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: API call help

Post by Danilo »

Wolfram wrote:but I get an Error if I try to load a File
Object dose not respond to method "fileSystemRepresentation"
Does it work for you with flag '#returnAbsoluteNames'?
In this case you get results like "file:///users/danilo/todo.rtf", but it could
be different URL for Network files.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: API call help

Post by wilbert »

Here's also a simplified version of Danilo's approach returning all absolute names in one string separated by |
Minimum requirement is OS X 10.6

Code: Select all

#showHiddenFiles        = 1 << 0
#allowMultipleSelection = 1 << 1

Procedure.s OpenFileRequester_(title.s, defaultdirectory.s = "", pattern.s = "", message.s = "", flags = 0)
  Protected NSPanel, NSArray, NSString
  
  NSPanel = CocoaMessage(0, 0, "NSOpenPanel openPanel")
  NSArray = CocoaMessage(0, CocoaMessage(0, 0, "NSString stringWithString:$", @pattern), "componentsSeparatedByString:$", @"|")
  
  CocoaMessage(0, NSPanel, "setTitle:$", @title)
  CocoaMessage(0, NSPanel, "setDirectoryURL:", CocoaMessage(0, 0, "NSURL URLWithString:$", @defaultdirectory))
  CocoaMessage(0, NSPanel, "setAllowedFileTypes:", NSArray)
  CocoaMessage(0, NSPanel, "setMessage:$", @message)
  
  If flags & #showHiddenFiles
    CocoaMessage(0, NSPanel, "setShowsHiddenFiles:", #YES)
  EndIf
  
  If flags & #allowMultipleSelection
    CocoaMessage(0, NSPanel, "setAllowsMultipleSelection:", #YES)
  EndIf
  
  If CocoaMessage(0, NSPanel, "runModal")
    NSString = CocoaMessage(0, CocoaMessage(0, NSPanel, "URLs"), "componentsJoinedByString:$", @"|")
    ProcedureReturn PeekS(CocoaMessage(0, NSString, "UTF8String"), -1, #PB_UTF8)
  Else
    ProcedureReturn ""
  EndIf
  
EndProcedure


Debug OpenFileRequester_("Please choose file(s) to load",
                         "/users/",
                         "pb|pbi|prefs|rtf|txt",
                         "Optional message:"+#CR$+"Please open a file for loading."+#CR$+"Second message line",
                         #allowMultipleSelection |
                         #showHiddenFiles )
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply