Date   

Re: Arg! Document window restoration. Again.

Keary Suska
 

Did something change recently? frameautosave has historically been the way to save a window’s frame, regardless of when the window was opened. Maybe you should take a second look. If you have a simple controller-window setup, you could also look at windowFrameAutosaveName.

Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"

On Aug 1, 2019, at 7:00 AM, Steve Mills via Groups.Io <sjmills=mac.com@groups.io> wrote:

On Jul 31, 2019, at 23:57:33, Jon Gotow <gotow@stclairsoft.com> wrote:

Can't you just set NSWindow.frameAutosaveName? Or does NSDocument get in the way of that?
From what I've experienced and read, that only helps for reopening docs on app launch, not on opening docs once launched. The OS only stores info for docs that were open when the app exits so it can restore the app to the same state (as long as you have "Close windows when quitting an app" turned off in System Prefs).

--
Steve Mills
Drummer, Mac geek




Re: Arg! Document window restoration. Again.

Steve Mills
 

On Jul 31, 2019, at 23:57:33, Jon Gotow <gotow@stclairsoft.com> wrote:

Can't you just set NSWindow.frameAutosaveName? Or does NSDocument get in the way of that?
From what I've experienced and read, that only helps for reopening docs on app launch, not on opening docs once launched. The OS only stores info for docs that were open when the app exits so it can restore the app to the same state (as long as you have "Close windows when quitting an app" turned off in System Prefs).

--
Steve Mills
Drummer, Mac geek


Re: Arg! Document window restoration. Again.

Jon Gotow
 

Can't you just set NSWindow.frameAutosaveName? Or does NSDocument get in the way of that?

- Jon

On Jul 31, 2019, at 10:09 PM, Steve Mills via Groups.Io <sjmills=mac.com@groups.io> wrote:

Doc and window restoration is great when relaunching the app, but I also want each document's window to open to their last frame when the user opens documents. I can not find the right place to make that happen. I supposed I'll need to subclass the window controller or window? What I thought would work was to grab the saved restoration data (which I saved in the document by calling -encodeRestorableStateWithCoder: and specifically adding the window frame with a custom key in -window:willEncodeRestorableState:), feed the data to an NSKeyedUnarchiver, and pass that to -restoreStateWithCoder: from my document subclass' -windowControllerDidLoadNib: method. But that appears to do nothing. It doesn't even get around to calling the document's -window:didDecodeRestorableState: override.


Arg! Document window restoration. Again.

Steve Mills
 

Doc and window restoration is great when relaunching the app, but I also want each document's window to open to their last frame when the user opens documents. I can not find the right place to make that happen. I supposed I'll need to subclass the window controller or window? What I thought would work was to grab the saved restoration data (which I saved in the document by calling -encodeRestorableStateWithCoder: and specifically adding the window frame with a custom key in -window:willEncodeRestorableState:), feed the data to an NSKeyedUnarchiver, and pass that to -restoreStateWithCoder: from my document subclass' -windowControllerDidLoadNib: method. But that appears to do nothing. It doesn't even get around to calling the document's -window:didDecodeRestorableState: override.

Every time I need to do something beyond the basics with window restoration, I dread it because I know it will suck.

--
Steve Mills
Drummer, Mac geek


Re: Does anyone know what this error means?

Steve Christensen
 

On Jul 23, 2019, at 3:44 PM, Alex Zavatone via Groups.Io <zav@...> wrote:

It looks like you are being limited for making too many requests in one period of time.

That’s my guess.


On Jul 23, 2019, at 1:47 PM, Rick Aurbach via Groups.Io <rlaurb@...> wrote:

I am building an app that accesses the Library of Congress Online Card Catalog. At this point, I'm mainly running from the Simulator. And sometimes when I issue the GET query, I get the following error response:


2019-07-23 13:40:55.657130-0500 BookCorner[1369:31794] CredStore - performQuery - Error copying matching creds.  Error=-25300, query={

    class = inet;

    "m_Limit" = "m_LimitAll";

    "r_Attributes" = 1;

    sync = syna;

}


Does anyone know: (a) what this means? (b) what's causing it, and (c) what I can do about it?

I appreciate your help.

Rick Aurbach


Re: Does anyone know what this error means?

Alex Zavatone
 

It looks like you are being limited for making too many requests in one period of time.

That’s my guess.


On Jul 23, 2019, at 1:47 PM, Rick Aurbach via Groups.Io <rlaurb@...> wrote:

I am building an app that accesses the Library of Congress Online Card Catalog. At this point, I'm mainly running from the Simulator. And sometimes when I issue the GET query, I get the following error response:


2019-07-23 13:40:55.657130-0500 BookCorner[1369:31794] CredStore - performQuery - Error copying matching creds.  Error=-25300, query={

    class = inet;

    "m_Limit" = "m_LimitAll";

    "r_Attributes" = 1;

    sync = syna;

}


Does anyone know: (a) what this means? (b) what's causing it, and (c) what I can do about it?

I appreciate your help.

Rick Aurbach


Re: Core Date migration

Dave Fernandes
 

If you are modifying the object, I believe you should be doing this in:
createDestinationInstances(forSource:in:manager:)

This has always worked for me. The validation method looks like a keep/don’t keep decision point, though I have never used it.


On Jul 22, 2019, at 11:56 AM, Steve Mills via Groups.Io <sjmills@...> wrote:

In my Core Data model, I've added a 2nd version with a new attribute. This attribute needs to be initialized to a sequential value upon migration from the old version. So I'm using a mapping model and a custom migration policy to set this new attribute's value on every entity object.

But, it's not sticking. Do I need to be doing something else in my performCustomValidationForEntityMapping:manager:error: method to cause the changes I've made to be saved? Or am I just interpreting the incredibly vague documentation for this method wrong?

-(BOOL) performCustomValidationForEntityMapping:(NSEntityMapping*)mapping manager:(NSMigrationManager*)manager error:(NSError* _Nullable __autoreleasing*)error
{
BOOL result = YES;

if([manager isKindOfClass:[DocumentMigrationManager class]]) {
Document* doc = ((DocumentMigrationManager*)manager).doc;
NSFetchRequest* fetchRequest = [NSFetchRequest new];
NSEntityDescription* assetEntDesc = [Asset entityInManagedObjectContext:manager.destinationContext];

fetchRequest.entity = assetEntDesc;

NSArray<Asset*>* asses = [manager.destinationContext executeFetchRequest:fetchRequest error:error];

for(Asset* ass in asses) {
// ass.order = @(doc.nextAssetOrder);
[ass setValue:@(doc.nextAssetOrder) forKey:AssetAttributes.order];
}
}

return result;
}

(And damn it, when is Mail going to let us change to 4 spaces per tab like *normal* people use? My radar for that has been ignored for years.)

--
Steve Mills
Drummer, Mac geek






Re: Core Date migration

Steve Mills
 

On Jul 23, 2019, at 12:54:04, Jim <jimcfl@gmail.com> wrote:

Do you call save on the context somewhere? I’ve not needed to use a mapping like this yet but it seems like if you’re changing attributes you’d want to save.
No, I wasn't sure if that was necessary. One would hope that the act of migration will save the migrated data to the store without the developer having to do anything. It doesn't say that in the migration doc. In fact, it says it's part of the default migration process:

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmMigrationProcess.html#//apple_ref/doc/uid/TP40004399-CH6-SW8

I've also gone the "normal" route of creating the new objects in configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error: and setting the new attribute's value there. Both ways work at that point in the migration, but then when addPersistentStoreWithType:configuration:URL:options:error: is called at the end, it once again goes through another migration that I expect would happen. My custom migration policy is created out of my control, so I can't set a custom property on it, nor can I add an object to any object's userInfo (NSEntityMapping, NSMigrationManager, etc). I need to be able to get back to my document from the migration policy, and I can't find a way to do that when the default migration happens. If I could, then I don't think I'd need to do the manual migration at all.

--
Steve Mills
Drummer, Mac geek


Does anyone know what this error means?

Rick Aurbach
 

I am building an app that accesses the Library of Congress Online Card Catalog. At this point, I'm mainly running from the Simulator. And sometimes when I issue the GET query, I get the following error response:


2019-07-23 13:40:55.657130-0500 BookCorner[1369:31794] CredStore - performQuery - Error copying matching creds.  Error=-25300, query={

    class = inet;

    "m_Limit" = "m_LimitAll";

    "r_Attributes" = 1;

    sync = syna;

}


Does anyone know: (a) what this means? (b) what's causing it, and (c) what I can do about it?

I appreciate your help.

Rick Aurbach


Re: Core Date migration

Jim
 

On Jul 22, 2019, at 8:56 AM, Steve Mills via Groups.Io <sjmills=mac.com@groups.io> wrote:

In my Core Data model, I've added a 2nd version with a new attribute. This attribute needs to be initialized to a sequential value upon migration from the old version. So I'm using a mapping model and a custom migration policy to set this new attribute's value on every entity object.

But, it's not sticking. Do I need to be doing something else in my performCustomValidationForEntityMapping:manager:error: method to cause the changes I've made to be saved? Or am I just interpreting the incredibly vague documentation for this method wrong?

-(BOOL) performCustomValidationForEntityMapping:(NSEntityMapping*)mapping manager:(NSMigrationManager*)manager error:(NSError* _Nullable __autoreleasing*)error
{
BOOL result = YES;

if([manager isKindOfClass:[DocumentMigrationManager class]]) {
Document* doc = ((DocumentMigrationManager*)manager).doc;
NSFetchRequest* fetchRequest = [NSFetchRequest new];
NSEntityDescription* assetEntDesc = [Asset entityInManagedObjectContext:manager.destinationContext];

fetchRequest.entity = assetEntDesc;

NSArray<Asset*>* asses = [manager.destinationContext executeFetchRequest:fetchRequest error:error];

for(Asset* ass in asses) {
// ass.order = @(doc.nextAssetOrder);
[ass setValue:@(doc.nextAssetOrder) forKey:AssetAttributes.order];
}
}

return result;
}
Do you call save on the context somewhere? I’ve not needed to use a mapping like this yet but it seems like if you’re changing attributes you’d want to save.

Jim Crate


Core Date migration

Steve Mills
 

In my Core Data model, I've added a 2nd version with a new attribute. This attribute needs to be initialized to a sequential value upon migration from the old version. So I'm using a mapping model and a custom migration policy to set this new attribute's value on every entity object.

But, it's not sticking. Do I need to be doing something else in my performCustomValidationForEntityMapping:manager:error: method to cause the changes I've made to be saved? Or am I just interpreting the incredibly vague documentation for this method wrong?

-(BOOL) performCustomValidationForEntityMapping:(NSEntityMapping*)mapping manager:(NSMigrationManager*)manager error:(NSError* _Nullable __autoreleasing*)error
{
BOOL result = YES;

if([manager isKindOfClass:[DocumentMigrationManager class]]) {
Document* doc = ((DocumentMigrationManager*)manager).doc;
NSFetchRequest* fetchRequest = [NSFetchRequest new];
NSEntityDescription* assetEntDesc = [Asset entityInManagedObjectContext:manager.destinationContext];

fetchRequest.entity = assetEntDesc;

NSArray<Asset*>* asses = [manager.destinationContext executeFetchRequest:fetchRequest error:error];

for(Asset* ass in asses) {
// ass.order = @(doc.nextAssetOrder);
[ass setValue:@(doc.nextAssetOrder) forKey:AssetAttributes.order];
}
}

return result;
}

(And damn it, when is Mail going to let us change to 4 spaces per tab like *normal* people use? My radar for that has been ignored for years.)

--
Steve Mills
Drummer, Mac geek


Re: Sheet takes seconds to update

Steve Mills
 

It must have something to do with NSTextFields (or any view in general) whose value uses bindings. The text fields and the progress bar in this sheet all use bindings to set their values. If I add a test field that does NOT use bindings, and a button to set that field's value to a new value every time, I can sit here and click that button every second, and the test field's value will update as expected, but each time I click, it seems to cause the 5-second delay to restart, so it always takes around 5 seconds from the last click of the test button until the regular fields and progress bar to update to their final value.

--
Steve Mills
Drummer, Mac geek


Re: Sheet takes seconds to update

Steve Mills
 

On Jul 10, 2019, at 11:38:28, Jon Gotow <gotow@stclairsoft.com> wrote:

Has control returned to your main event loop, or are you still doing some kind of processing during the delay time?
Control has returned.

When you change the button name, etc, is that all being done from the main thread and not from a background thread?
Changing a UI object has to be done from the main thread, so I'm doing it from dispatch_async(dispatch_get_main_queue(), …), and I've verified that the block does get run very soon after being dispatched, so that's not what's causing the draw to be delayed. I don't think this will help, but here's the stack for the draw thread when it finally does the final draw. Note that it's NOT the main thread (which is OK here) - but why is it taking so long for this draw thread to be fired off?

#0 0x00000001000a1ed4 in -[TestLabel drawRect:] at /Users/tut/Projects/Image Chest/Image Chest/ProgressController.m:183
#1 0x00007fff4c81641e in _NSViewDrawRect ()
#2 0x00007fff4c814cac in -[NSView(NSInternal) _recursive:displayRectIgnoringOpacity:inContext:shouldChangeFontReferenceColor:stopAtLayerBackedViews:] ()
#3 0x00007fff4c81463f in __46-[NSView(NSLayerKitGlue) drawLayer:inContext:]_block_invoke ()
#4 0x00007fff4c81439c in -[NSView(NSLayerKitGlue) _drawViewBackingLayer:inContext:drawingHandler:] ()
#5 0x00007fff59b18932 in CABackingStoreUpdate_ ()
#6 0x00007fff59b7a2f1 in ___ZN2CA5Layer8display_Ev_block_invoke ()
#7 0x00007fff59b17b24 in -[CALayer _display] ()
#8 0x00007fff4c81394e in _NSBackingLayerDisplay ()
#9 0x00007fff4c7f7e4f in -[_NSViewBackingLayer display] ()
#10 0x00007fff59b17055 in CA::Layer::display_if_needed(CA::Transaction*) ()
#11 0x00007fff59b0527a in CA::Context::commit_transaction(CA::Transaction*) ()
#12 0x00007fff59b048c2 in CA::Transaction::commit() ()
#13 0x00007fff59b307da in CA::Transaction::release_thread(void*) ()
#14 0x0000000100523183 in _pthread_tsd_cleanup ()
#15 0x0000000100526299 in _pthread_exit ()
#16 0x0000000100522f12 in _pthread_wqthread_exit ()
#17 0x0000000100522048 in _pthread_wqthread ()
#18 0x0000000100521e01 in start_wqthread ()

--
Steve Mills
Drummer, Mac geek


Re: Sheet takes seconds to update

Jon Gotow
 

Has control returned to your main event loop, or are you still doing some kind of processing during the delay time? When you change the button name, etc, is that all being done from the main thread and not from a background thread?

- Jon

On Jul 10, 2019, at 11:31 AM, Steve Mills via Groups.Io <sjmills=mac.com@groups.io> wrote:

I'm putting up a sheet from a nib to display progress while I process things. When processing is done, I change the button name and ensure the progress bar is set to max. At that point, one of the labels should be showing something like "1 of 1", but it's still stuck at "0 of 1", EVEN THOUGH I know for a fact that its stringValue has already been set to "1 of 1". If I set a breakpoint on the label's drawRect, it can take 1 to 5 seconds before drawRect will be called for the final time.

WTH's going on?


Sheet takes seconds to update

Steve Mills
 

I'm putting up a sheet from a nib to display progress while I process things. When processing is done, I change the button name and ensure the progress bar is set to max. At that point, one of the labels should be showing something like "1 of 1", but it's still stuck at "0 of 1", EVEN THOUGH I know for a fact that its stringValue has already been set to "1 of 1". If I set a breakpoint on the label's drawRect, it can take 1 to 5 seconds before drawRect will be called for the final time.

WTH's going on?

--
Steve Mills
Drummer, Mac geek


Re: Using /dev/stdout in a sandboxed app

Sandor Szatmari
 

Awesome!  

After several rereads I realize that Ffmpeg documentation does state this, but not in clear terms.

It states that any file/stream can be referenced as a pair, <file_no:stream_no>, hence pipe:1 == stdout

It talks about pipe almost within the same breath, but doesn’t explicitly connect the dots and say, to reference stdout/stdin/stderr you literally use the word pipe.

Reference section 2 (Description)

Sandor

On Jul 9, 2019, at 07:38, Graham Cox <graham@...> wrote:

Ah, that worked a treat!!! Thanks so much Sandor.

—Graham




On 9 Jul 2019, at 9:21 pm, Sandor Szatmari <admin.szatmari.net@...> wrote:

I think you would pass

-progress pipe:1 will write out to stdout, 

Or

pipe:2 to stderr.

Then just read from the pipe you associate.

I haven’t tried it myself, google told me to do it.

It might mess up your parsing if other messages are interspersed in the progress messages, but hopefully you can distinguish between the two types of information.  


Sandor


Re: Using /dev/stdout in a sandboxed app

Bill Pitcher
 

looking back I went with

//! Connect the Output Pipes
[aTask setStandardOutput:[NSPipe pipe]];
[aTask setStandardError:[aTask standardOutput]];


//! Tell the Pipe to notify to read in the background and post a notification
[[[aTask standardOutput] fileHandleForReading] readInBackgroundAndNotify];

then grab the data as it comes in.

Cheers
Bill

On 9 Jul 2019, at 4:42 pm, Graham Cox <graham@mapdiva.com> wrote:

Hi Chris,

actually I think I am doing that.

it’s a while since i put this code together, and exactly what the arguments are is not so clear now. I set the NSTask.standardOutput to an NSPipe, and I have a callback block that deals with that.

However, I’m also passing the -progress argument to ffmpeg as /dev/stdout. Now ffmpeg has a million options, and the documentation is rather terse. All it says for the -progress option is:

<Screen Shot 2019-07-09 at 4.26.06 pm.png>

I pass /dev/stdout as the url argument because what else could it be? My assumption was that NSTask’s standardOutput basically read from there, it was just a convenient place to hook in. The fact it worked led me never to further question that until now. If you don’t pass the -progress parameter, ffmpeg doesn’t send anything.

So the problem isn’t so much the NSTask, but what to pass as a url parameter to the -progress option.

The gist of the code is (with irrelevant stuff cut for clarity and brevity)

NSPipe* progressPipe = [NSPipe pipe];

progressPipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle* handle )
{
// parse progress reports to update UI with certain info
};

// create the FFMPEG task:

NSString* execPath = [[[self class] ffMPEGURL] path];
NSArray* codecArgs = [[[self class] ffMPEGCodecForOption:self.format] componentsSeparatedByString:@" "];

if( codecArgs.count > 0 )
{
if( self.outputFileURL == nil )
[self requestDelegateCreatesFile];

NSAssert( self.outputFileURL, @"unable to proceed - no output file");

NSMutableArray* args = [NSMutableArray array];

[args addObjectsFromArray:@[@"-loglevel", @"error", @"-i", url.absoluteString]];
[args addObjectsFromArray:codecArgs];
[args addObjectsFromArray:@[@"-progress", @"/dev/stdout", self.outputFileURL.path]]; /<——————————————— set up -progress option

XVLOG(@"ffmpeg arguments: %@", args);

NSTask* theTask = [[NSTask alloc] init];

NSAssert( theTask, @"unable to create NSTask for ffmpeg subprocess");

theTask.launchPath = execPath;
theTask.arguments = args;
theTask.standardOutput = progressPipe;
theTask.qualityOfService = NSQualityOfServiceUserInitiated;

theTask.terminationHandler = ^(NSTask* task)
{
// termination handler
};

self.ffMPEGTask = theTask;

[theTask release];

if( self.ffMPEGTask )
{
[self.ffMPEGTask launch]; // GO!!!
self.status = XVMediaDownloaderRunning;
self.filesize = 0;
}
}



—Graham



On 9 Jul 2019, at 4:01 pm, Chris Hanson <cmhanson@eschatologist.net> wrote:

Sure, just use NSTask’s own standardInput, standardOutput, and standardError support with NSPipe. No need to tell the task to send its stdout to some intermediate file that your app then opens and reads from. (Whether it’s in /dev or anywhere else.)

-- Chris




Re: Using /dev/stdout in a sandboxed app

Graham Cox
 

Ah, that worked a treat!!! Thanks so much Sandor.

—Graham




On 9 Jul 2019, at 9:21 pm, Sandor Szatmari <admin.szatmari.net@...> wrote:

I think you would pass

-progress pipe:1 will write out to stdout, 

Or

pipe:2 to stderr.

Then just read from the pipe you associate.

I haven’t tried it myself, google told me to do it.

It might mess up your parsing if other messages are interspersed in the progress messages, but hopefully you can distinguish between the two types of information.  


Sandor


Re: Using /dev/stdout in a sandboxed app

Sandor Szatmari
 

I think you would pass

-progress pipe:1 will write out to stdout, 

Or

pipe:2 to stderr.

Then just read from the pipe you associate.

I haven’t tried it myself, google told me to do it.

It might mess up your parsing if other messages are interspersed in the progress messages, but hopefully you can distinguish between the two types of information.  


Sandor

On Jul 9, 2019, at 02:42, Graham Cox <graham@...> wrote:

Hi Chris,

actually I think I am doing that.

it’s a while since i put this code together, and exactly what the arguments are is not so clear now. I set the NSTask.standardOutput to an NSPipe, and I have a callback block that deals with that.

However, I’m also passing the -progress argument to ffmpeg as /dev/stdout. Now ffmpeg has a million options, and the documentation is rather terse. All it says for the -progress option is:

<Screen Shot 2019-07-09 at 4.26.06 pm.png>

I pass /dev/stdout as the url argument because what else could it be? My assumption was that NSTask’s standardOutput basically read from there, it was just a convenient place to hook in. The fact it worked led me never to further question that until now. If you don’t pass the -progress parameter, ffmpeg doesn’t send anything.

So the problem isn’t so much the NSTask, but what to pass as a url parameter to the -progress option.

The gist of the code is (with irrelevant stuff cut for clarity and brevity)

NSPipe* progressPipe = [NSPipe pipe];


progressPipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle* handle )
{
// parse progress reports to update UI with certain info
};


// create the FFMPEG task:


NSString* execPath = [[[self class] ffMPEGURL] path];
NSArray* codecArgs = [[[self class] ffMPEGCodecForOption:self.format] componentsSeparatedByString:@" "];


if( codecArgs.count > 0 )
{
if( self.outputFileURL == nil )
[self requestDelegateCreatesFile];


NSAssert( self.outputFileURL, @"unable to proceed - no output file");


NSMutableArray* args = [NSMutableArray array];


[args addObjectsFromArray:@[@"-loglevel", @"error", @"-i", url.absoluteString]];
[args addObjectsFromArray:codecArgs];
[args addObjectsFromArray:@[@"-progress", @"/dev/stdout", self.outputFileURL.path]];  /<——————————————— set up -progress option


XVLOG(@"ffmpeg arguments: %@", args);


NSTask* theTask = [[NSTask alloc] init];


NSAssert( theTask, @"unable to create NSTask for ffmpeg subprocess");


theTask.launchPath = execPath;
theTask.arguments = args;
theTask.standardOutput = progressPipe;
theTask.qualityOfService = NSQualityOfServiceUserInitiated;

theTask.terminationHandler = ^(NSTask* task)
{
// termination handler
};


self.ffMPEGTask = theTask;


[theTask release];


if( self.ffMPEGTask )
{
[self.ffMPEGTask launch]; // GO!!!
self.status = XVMediaDownloaderRunning;
self.filesize = 0;
}
}



—Graham



On 9 Jul 2019, at 4:01 pm, Chris Hanson <cmhanson@...> wrote:

Sure, just use NSTask’s own standardInput, standardOutput, and standardError support with NSPipe. No need to tell the task to send its stdout to some intermediate file that your app then opens and reads from. (Whether it’s in /dev or anywhere else.)

 -- Chris






Re: Using /dev/stdout in a sandboxed app

Graham Cox
 

Hi Chris,

actually I think I am doing that.

it’s a while since i put this code together, and exactly what the arguments are is not so clear now. I set the NSTask.standardOutput to an NSPipe, and I have a callback block that deals with that.

However, I’m also passing the -progress argument to ffmpeg as /dev/stdout. Now ffmpeg has a million options, and the documentation is rather terse. All it says for the -progress option is:


I pass /dev/stdout as the url argument because what else could it be? My assumption was that NSTask’s standardOutput basically read from there, it was just a convenient place to hook in. The fact it worked led me never to further question that until now. If you don’t pass the -progress parameter, ffmpeg doesn’t send anything.

So the problem isn’t so much the NSTask, but what to pass as a url parameter to the -progress option.

The gist of the code is (with irrelevant stuff cut for clarity and brevity)

NSPipe* progressPipe = [NSPipe pipe];


progressPipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle* handle )
{
// parse progress reports to update UI with certain info
};


// create the FFMPEG task:


NSString* execPath = [[[self class] ffMPEGURL] path];
NSArray* codecArgs = [[[self class] ffMPEGCodecForOption:self.format] componentsSeparatedByString:@" "];


if( codecArgs.count > 0 )
{
if( self.outputFileURL == nil )
[self requestDelegateCreatesFile];


NSAssert( self.outputFileURL, @"unable to proceed - no output file");


NSMutableArray* args = [NSMutableArray array];


[args addObjectsFromArray:@[@"-loglevel", @"error", @"-i", url.absoluteString]];
[args addObjectsFromArray:codecArgs];
[args addObjectsFromArray:@[@"-progress", @"/dev/stdout", self.outputFileURL.path]];  /<——————————————— set up -progress option


XVLOG(@"ffmpeg arguments: %@", args);


NSTask* theTask = [[NSTask alloc] init];


NSAssert( theTask, @"unable to create NSTask for ffmpeg subprocess");


theTask.launchPath = execPath;
theTask.arguments = args;
theTask.standardOutput = progressPipe;
theTask.qualityOfService = NSQualityOfServiceUserInitiated;

theTask.terminationHandler = ^(NSTask* task)
{
// termination handler
};


self.ffMPEGTask = theTask;


[theTask release];


if( self.ffMPEGTask )
{
[self.ffMPEGTask launch]; // GO!!!
self.status = XVMediaDownloaderRunning;
self.filesize = 0;
}
}



—Graham



On 9 Jul 2019, at 4:01 pm, Chris Hanson <cmhanson@...> wrote:

Sure, just use NSTask’s own standardInput, standardOutput, and standardError support with NSPipe. No need to tell the task to send its stdout to some intermediate file that your app then opens and reads from. (Whether it’s in /dev or anywhere else.)

 -- Chris





401 - 420 of 1422