Re: Decoding FxPlug custom params from FCP-XML
Re: Decoding FxPlug custom params from FCP-XML
- Subject: Re: Decoding FxPlug custom params from FCP-XML
- From: Robert Monaghan <email@hidden>
- Date: Tue, 27 Apr 2010 15:37:23 -0700
Thanks! This helps tremendously!
bob.
On Apr 27, 2010, at 3:26 PM, Steve Christensen wrote:
> Since I noticed my name mentioned at the beginning of the thread, I figured I'd jump in. I only do the encoding side in my case, but did find that I have to run the parameter value through an archiver twice before UUEncoding, like this:
>
>
> // archive the original object into a data blob
> NSMutableData* archivedValue = [NSMutableData data];
> NSMutableData* archivedData = [NSMutableData data];
> NSKeyedArchiver* archiver;
>
> archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:archivedValue] autorelease];
> [archiver encodeObject:parameterValue];
> [archiver finishEncoding];
>
> // then archive the data blob
> archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:archivedData] autorelease];
> [archiver encodeObject:archivedValue];
> [archiver finishEncoding];
>
> return UUEncode(archivedData, false);
>
>
> I have also appended the UUEncode/UUDecode functions I'm using. At this point I don't remember the origins of any original sources, but I had used them to create a version to my liking. I added an extra parameter to turn on/off the standard feature of adding a line break, since it is not included when encoding for FCP.
>
> steve
>
>
> On Apr 27, 2010, at 10:11 AM, Robert Monaghan wrote:
>
>> Hi Eryk!
>>
>> I am about to implement some of this kind of code too. Is there a boiler-plate code sample for the uuencode/decode that Apple can point to?
>>
>> Thanks
>>
>> Bob
>>
>> Sent from my iPhone
>>
>> On Apr 27, 2010, at 9:43, Kristian Harms <email@hidden> wrote:
>>
>>> Thank you Eryk.
>>>
>>> It was indeed a length-related issue. The NSKeyedUnarchiver's init no longer throws.
>>>
>>> Regarding the uuencoding, am I right in guessing you have rolled your own implementation? The reason is that it doesn't seem to have been encoded using any of the uuencoding implementations I have found, which insert a newline at regular intervals in the encoded data. It would be nice if you could document any peculiarities of your uuencode.
>>>
>>> Best regards,
>>> Kristian Harms
>>>
>>> Den 2010-04-26 11:02 PM, skrev Eryk Vershen:
>>>> Kristian,
>>>>
>>>> From the link you gave it is clear you had Paul's response; that should be the right thing to do. I agree the uudecode shouldn't have a problem. The string of bytes that NSKeyedUnarchiver mentions in the error is the string 'bplist00' (i.e. the start of a binary plist). I believe keyed archives are stored using plists these days, so that seems right.
>>>>
>>>> Perhaps you've messed up the length of the data?
>>>>
>>>> It's probably complaining because it's having a failure reading the plist (qua plist).
>>>>
>>>> -eryk
>>>>
>>>>
>>>> On Apr 26, 2010, at 12:15 PM, Kristian Harms wrote:
>>>>
>>>>
>>>>> Hi,
>>>>>
>>>>> I'm doing something similar to what Steve Christensen asked about in this email to the list, a year ago:
>>>>>
>>>>> http://lists.apple.com/archives/Pro-apps-dev/2009/Feb/msg00036.html
>>>>>
>>>>> In brief, I want to grab from the FCP XML the parameter value for any custom parameters in my FxPlugs and deserialise them. However, when I come to the point where I instantiate the NSKeyedUnarchiver with my NSData, which I have uudecoded based on the string I acquire from the XML, I actually get an Objective-C exception, of type NSInvalidArgumentException, and with reason:
>>>>>
>>>>> *** -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30)
>>>>>
>>>>> This happens on the init call itself, and not on the [unarchiver decodeObject] call that the link above recommends doing next.
>>>>>
>>>>> I'm stumped as to how to procede. There are no obvious things I've done that could compromise the data -- the only point where a character encoding is involved is when I extract the char* from the NSString holding the uuencoded data, but uuencoded data should be representable as 7-bit ascii anyway, so choosing utf8, latin1 or even ascii should work fine there. There are no character encodings involved after the point where I uudecode.
>>>>>
>>>>> Version info: Running FCP 7.0.2 and plugin compiled using FxPlug SDK 1.2.5, on top of OS X 10.5.
>
>
>
> //--------------------------------------------------------------------------------
> NSInteger UUEncodeStringBufferSize(NSInteger dataLength, bool hasNewlines)
> {
> return (dataLength * 4 / 3) + (((dataLength + 44) / 45) * (1 + (hasNewlines ? 2 : 0))) + 1;
> }
>
> //--------------------------------------------------------------------------------
> NSInteger UUEncode(const uint8_t* dataBuffer, NSInteger dataLength, uint8_t* stringBuffer, bool hasNewlines)
> {
> #define EncodeByte_(ch) ((ch) != 0) ? (((ch) & 0x3f) + ' ') : '`'
>
> NSInteger dataIndex = 0;
> NSInteger stringIndex = 0;
> NSInteger lineLength;
>
> // break up the data into lines of up to 45 bytes...
> while ((lineLength = MIN(dataLength - dataIndex, 45)) > 0)
> {
> // encode the line length
> stringBuffer[stringIndex++] = EncodeByte_(lineLength);
>
> // encode the data bytes for the current line
> for (; lineLength > 0; lineLength -= 3)
> {
> NSUInteger data0 = dataBuffer[dataIndex + 0], data1 = 0, data2 = 0;
>
> // handle buffers that aren't an even multiple of 3 by avoiding reads off the end
> switch (lineLength)
> {
> default:
> data2 = dataBuffer[dataIndex + 2];
>
> case 2:
> data1 = dataBuffer[dataIndex + 1];
>
> case 1:
> break;
> }
>
> stringBuffer[stringIndex + 0] = EncodeByte_((data0 >> 2));
> stringBuffer[stringIndex + 1] = EncodeByte_((data0 << 4) | (data1 >> 4));
> stringBuffer[stringIndex + 2] = EncodeByte_((data1 << 2) | (data2 >> 6));
> stringBuffer[stringIndex + 3] = EncodeByte_((data2 & 0x3f));
>
> dataIndex += 3;
> stringIndex += 4;
> }
>
> // the uuencode spec puts "\r\n" at the end of each line but there might be cases where they're not included
> if (hasNewlines)
> {
> stringBuffer[stringIndex + 0] = '\r';
> stringBuffer[stringIndex + 1] = '\n';
> stringIndex += 2;
> }
> }
>
> stringBuffer[stringIndex] = '\0';
>
> return stringIndex;
> }
>
> //--------------------------------------------------------------------------------
> NSString* UUEncode(const NSData* data, bool hasNewlines)
> {
> if (data != nil)
> {
> NSInteger dataLength = [data length];
> uint8_t stringBuffer[UUEncodeStringBufferSize(dataLength)];
>
> UUEncode(static_cast<const uint8_t*>([data bytes]), dataLength, stringBuffer, hasNewlines);
>
> return [NSString stringWithCString:reinterpret_cast<char*>(stringBuffer) encoding:NSASCIIStringEncoding];
> }
>
> return nil;
> }
>
> //--------------------------------------------------------------------------------
> NSInteger UUDecode(const uint8_t* stringBuffer, NSInteger stringLength, uint8_t* dataBuffer, bool hasNewlines)
> {
> #define DecodeByte_(ch) ((ch) - ' ') & 0x3f
>
> NSInteger dataIndex = 0;
> NSInteger stringIndex = 0;
>
> while (stringIndex < stringLength)
> {
> // decode the length of the current line
> NSInteger lineLength = DecodeByte_(stringBuffer[stringIndex++]);
>
> // decode the data bytes for the current line
> for (; lineLength > 0; lineLength -= 3)
> {
> NSUInteger string0 = DecodeByte_(stringBuffer[stringIndex + 0]);
> NSUInteger string1 = DecodeByte_(stringBuffer[stringIndex + 1]);
> NSUInteger string2 = DecodeByte_(stringBuffer[stringIndex + 2]);
> NSUInteger string3 = DecodeByte_(stringBuffer[stringIndex + 3]);
>
> dataBuffer[dataIndex++] = (string0 << 2) | (string1 >> 4);
> if (lineLength >= 2)
> {
> dataBuffer[dataIndex++] = (string1 << 4) | (string2 >> 2);
> if (lineLength >= 3)
> {
> dataBuffer[dataIndex++] = (string2 << 6) | (string3 >> 0);
> }
> }
>
> stringIndex += 4;
> }
>
> // the uuencode spec puts "\r\n" at the end of each line but there might be cases where they're not included
> if (hasNewlines)
> stringIndex += 2;
> }
>
> return dataIndex;
> }
>
> //--------------------------------------------------------------------------------
> NSData* UUDecode(const NSString* string, bool hasNewlines)
> {
> if (string != nil)
> {
> NSInteger stringLength = [string length];
> uint8_t stringBuffer[stringLength + 1];
>
> if ([string getCString:(char*)stringBuffer maxLength:(stringLength + 1) encoding:NSASCIIStringEncoding])
> {
> uint8_t dataBuffer[stringLength];
> NSInteger dataLength = UUDecode(stringBuffer, stringLength, dataBuffer, hasNewlines);
>
> return [NSData dataWithBytes:dataBuffer length:dataLength];
> }
> }
>
> return nil;
> }
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Pro-apps-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden