I have an app, myApp, which is used to display images, (.jpg, png), in a folder, “Debut”; as a new image is added to the folder it is displayed in an image well in myApp.
The images are added when I click on “Take snapshot” in another program, Debut, the program name is Debut and the folder name is also Debut.
So, to take a snapshot, Debut has to be the active app and myApp has to be a background process.
My app has a timer in Mode 2, which polls for folderitem count in “Debut”.
What happens is that when a snapshot is taken the image goes into the folder, “Debut”, but because myApp is in the background it is not aware that the folder count has changed.
How can I make myApp which is in the background to process to still poll for folderitem count in “Debut”.
File system events
Basically you register to be notified when certain things happen in the file system & when they do you get a notification
You can then do whatever is appropriate - like moving your app to be in the foreground
MacOSLIb has them for OS X
MBS plugins have something for OS X & Windows
I would also suggest perhaps using IPC sockets, you could then send messages between the two apps. If you wanted, you could even send the image data over the socket and avoid having to hit the disk, which would save power consumption.
IPC sockets would be a good way to do it. I have been advised about IPC sockets for various things previously, but I have never been able to do it, an example project would be fantastic, do you have a link for any IPC example project that you would like to share?
Is this what you are referring to? FileManager/FSIterator/Methods/VisibleCount.
Function VisibleCount(f as FolderItem) As UInt32
if not f.Exists then
return 0
end if
if not f.Directory then
return 0
end if
#if targetMacOS
soft declare function FSCatalogSearch lib CarbonLib (iterator as Ptr, ByRef searchCriteria as FSSearchParams, maximumObjects as UInt32, ByRef actualObjects as UInt32, ByRef containerChanged as Boolean, whichInfo as Uint32, catalogInfos as Ptr, refs as Ptr, specs as Ptr, names as Ptr) as Int16
dim iterator as new FSIterator(f, FSIterator.kFSIterateFlat)
//build search criteria
const fsSBFlFndrInfo = 8 //For files only search by the files Finder info.
const fsSBDrUsrWds = 8 //For directories only search by the directorys Finder info.
const fsSBFlParID = 8192 //For files only search by the files parent ID.
dim criteria as FSSearchParams
criteria.searchTime = 0
criteria.searchBits = fsSBFlFndrInfo + fsSBFlParID
criteria.searchNameLength = 0
criteria.searchName = nil
//add parent dir criterion
dim searchInfo1 as new MemoryBlock(FSCatalogInfo.Size)
searchInfo1.UInt32Value(4) = f.MacDirID
searchInfo1.Long(80) = FileManager.kIsInvisible
criteria.searchInfo1 = searchInfo1
dim searchInfo2 as new MemoryBlock(FSCatalogInfo.Size)
searchInfo2.Long(80) = FileManager.kIsInvisible
criteria.searchInfo2 = searchInfo2
const maximumObjects = 16
dim actualObjects as UInt32
dim containerChanged as Boolean
dim nameArray as new MemoryBlock(maximumObjects*HFSUniStr255.Size)
dim OSErr as Int16 = FSCatalogSearch(iterator, criteria, maximumObjects, actualObjects, containerChanged, 0, nil, nil, nil, nameArray)
if OSErr <> noErr then
break
end if
return actualObjects
I’ve seen this …
Private Sub HandleEvent(numEvents as integer, eventPaths as Ptr, eventFlags as Ptr, eventIDs as Ptr) #if TargetMacOS
#pragma DisableBackgroundTasks
#pragma StackOverflowChecking false
declare function CFArrayGetStringAtIndex lib CarbonLib alias "CFArrayGetValueAtIndex" (theArray as Ptr, idx as Integer) as CFStringRef
declare function CFArrayGetValueAtIndex lib CarbonLib alias "CFArrayGetValueAtIndex" (theArray as Ptr, idx as Integer) as Ptr
declare function CFNumberGetValue lib CarbonLib (nbr as Ptr, theType as integer, outValue as Ptr) as Boolean
const kCFNumberIntType = 9
const kCFNumberLongType = 10
dim id as UInt64
dim path as String
dim flags as UInt32
'dim mb as new MemoryBlock( 8 )
dim mb2, mb3 as MemoryBlock
'dim p as Ptr
dim arp() as string
dim arf() as int32
dim arid() as UInt64
dim f as FolderItem
mb2 = eventFlags
mb3 = eventIDs
for i as integer=0 to numEvents - 1
path = CFArrayGetStringAtIndex( eventPaths, i )
arp.Append path
if RelativeTo<>nil then
f = GetFolderItemFromPOSIXPath( RelativeTo.POSIXPath + "/" + path )
else
f = GetFolderItemFromPOSIXPath( path )
end if
flags = mb2.UInt32Value( i * 4 )
arf.Append flags
id = mb3.UInt64Value( i * 8 )
arid.Append id
next
RaiseEvent FilesystemModified( arp, arf, arid )
[quote=263250:@Lennox Jacob]My app has a timer in Mode 2, which polls for folderitem count in “Debut”.
What happens is that when a snapshot is taken the image goes into the folder, “Debut”, but because myApp is in the background it is not aware that the folder count has changed.[/quote]
I understand that there may be more efficient ways of doing this (depending on how many files are in that folder), but the OPs question was why did FolderItem.count not work whilst his application was in the background.
FolderItem.count called from a Timer should normally work whether the application if foreground or background. I knocked up a quick test app in MacOS and it works just fine when sent to the background…
[code] dim f as FolderItem
f = New FolderItem (SpecialFolder.Desktop)
label1.Text = Str (f.Count)[/code]
This is confusing because it should not be true. The timer continues to fire even when your app does not have focus. I’d look at this a little more closely. That said, using filesystem events is a more elegant approach, albeit more difficult.
I downloaded the latest version of macoslib, v.187 and when I ran it I got this message "Test in Cocoa module failed: ".
I saw the example under Examples/Convenience Extensions and when I ran it and added a folder item to the UserHome folder nothing happened. I figure that it does not work on my system - Mac OS X 10.11.4 (15E65)
I added a TextField to the window and added this to the timer
TextField3.Text = Str(Ticks)
When the Timer is activated TextField3.Text changes as expected
When the app is in the background the timer still functions, confirming that the timer works even if the app is in the background.
My app seems to be working now, with and without that testField. I don’t know what the problem was.
I would prefer using filesystem events since it is a more elegant approach as Tim mentioned, any advice on how this can be achieved? Macoslib does not appear to support Cocoa for this.