Pattrstorage doesn't overwrite preset files in standalone

Bruno Zamborlin's icon

Dear all,

I'm experiencing some trouble using pattrstorage in standalones.

Basically, what I want to do is read and write some parameters in a XML file (or JSON, same thing) from a standalone application.
While in the patch version everything works fine, in the standalone it is able to read the file and load the parameters, but when I try to overwrite the XML file the follow error occurs:

pattrstorage: error -1 in sysfile write: tried to write 174, wrote 174

Please note that the permissions of the XML file (as well as the application and the parent folder) are set to "read and write" for all users.
I tried in different machines and repaired the disk permissions. The problem is always the same.
OSX 10.5.8 + Max 5.1.3

I made a simple test patch that explains clearly the issue (see below).
Just export it as a standalone and copy the XML file inside it in order to reproduce the same problem.

Max Patch
Copy patch and select New From Clipboard in Max.

Any help is more than welcome.
Best,
Bruno

Léopold Frey's icon

Hello,

I'm having exactly the same troubles getting pattrstorage to work in standalone.
It seems that the preset file is embedded in the mxf file and thus can not be overwritten.
Is it possible not to include the preset file in the mxf file ?
(json or xml, same problem but different error messages).

I've never had this problem before, can anybody reproduce this ?

Max Patch
Copy patch and select New From Clipboard in Max.

See example below with steps to reproduce.

@ Bruno : a work around is to set your [pattrstorage test @autorestore 0], not to write your preset file in max (the pattrstorage should not have a reference to any preset file so that this file will not be included in the standalone/collective), then it should work.

Anyway it isn't really practical when going from max to collective/standalone back and forth.
A nice addition would be an embedincollective attribute.

Macbook Pro 2.4GHz Intel Core 2 Duo / Mac OS 10.5.8 / Max 5.1.4 (42462)
Same problem on a black Macbook (haven't got the spec right now) but same OS and max version.

Thanks

Léo

ch's icon

to léo :

I can't reproduce. Your example just work fine here...

a+,
Charles

os 10.5.6 - max 5.1.4

Léopold Frey's icon

Thanks raja,

@savemode 0 + @autorestore 0 + explicitly loading the file on patch load seems the way to go.

I wonder why I never had this problem before.

I remember having read something about improvements on including files in collectives in one the 5.x version changes but can not find it anymore, I guess it's related.

Thanks,

Léo

scarbo's icon

hello, i have the same problem on my Density GS, isn't question @savemode 0 + @autorestore 0 because its an arbitrary problem. When compile standalone, some time it work, some other no, i have not understood yet.
I tried also purge all pattrstorage when [loadbang], but still the problem
thanks
ape

Léopold Frey's icon

Hello Scarbo,

you're right, raja's solution doesn't completely solved the problem right now.
Though it should.
But the workaround is to be sure that the pattrstorage doesn't have a reference to a file when creating the standalone.
Copy the object and paste it in a text window, the following line must not be present :
"autorestore" : "MyPresetFile.json"
otherwise the json file will be embedded in the collective and thus be read-only.

From what I understand, @autorestore 0 avoids loading the file on start up and @savemode 0 avoids automatically saving the file while saving the patch, so this should be the way to go but from time to time it doesn't work, I'll investigate further when I'll have time.

Hope this helps.

Léo

scarbo's icon

ok, in fact if compiling standalone without loading a project (and so dirty pattrstorage), the problem it does not happen, viceversa... good to know :-) thanks
regards

scarbo's icon

ok, i'll wait for some news, thanks

ch's icon

Ok... I just get the same issue today..

>> Copy the object and paste it in a text window,
>> the following line must not be present :"autorestore" : "MyPresetFile.json"

nice tip.
As well it seems to me that it does not work if pattrstorage got some priorities.
so opening the object as text, the following must not be present :

"priority" : {
...
...
}

rolnxyz's icon

OSX 10.6.4

Max/MSP 5.1.4

I also can't get this working.

Does anybody have a patch that saves pattrstorage entries to a file and restores from the same file? And that works when building an application?

I have tried everything in this post, and also other stuff on my own. I am starting to consider doing the saving and loading from a c++ external.

Léopold Frey's icon

Hello,

in latest max (5.1.7) a new attribute as been introduced in pattrstorage.
It should solve this standalone problem.
I haven't got time to test it right now but you should give it a try :

"
pattrstorage: new @fileusagemode - when 1, JSON/XML storage files will not be included in collectives and standalones. Default = 0 (include storage file)
"

léo

pdelges's icon

If you copy your .json file into the package by yourself, this seems to work:

@autorestore 1 @savemode 0 @fileusagemode 1

(Max5.1.7 under MacOS X.6.5)

Andrew Pask's icon

Don't you mean

@autorestore 1 @savemode 3 @fileusagemode 1

@savemode 0 does not save any changes to pattrstorage.

With @savemode 3 I can make changes in a standalone app and have them restore correctly when restarting the app.Also you have to remember to copy the json file in to the package next to the .mxf on Mac or the enclosing folder on Windows

-A

P.S. - if you use savemode 3, then you shouldn't need to use writeagain

pdelges's icon

Andrew,

you're right, of course... I forgot to write that I explicitly sent a writeagain with closebang. I just tried @savemode 3 and it does work. I put the .json file in the package's Resources folder (OS X.6.5).

rolnxyz's icon

Just to confirm. After upgrading to 5.1.7 I was able to save.

Makrotulpa's icon

I'm having this very problem in 5.1.8 / osx 10.6.8

I've put some vizzie objects that use pattrstorage together into an application for my bandmate to use.
Shift-click works in my max5 but in the standalone application I get "error -1 writing [filename.json]"
I've tried explicitly including the files when I compile.
I've tried changing the pattrstorage argument to "@autorestore 1 @savemode 3 @fileusagemode 1"
I've tried moving the .json files into Resources and also into the directory with the .mxf file.
Still does not work.

orange_glass's icon

This one's been driving me mad I am on OSX 10.5.8 max 5.1.9

I've tried copying a data.json file that is references into the app package, I've tried not doing that, manually saving to a file once the app is built. I just can't get any sort of persistence. Please help me.

Max Patch
Copy patch and select New From Clipboard in Max.

Here is my simple patch that fails. Am I missing anything?

seejayjames's icon

@orange
I think you have to use the complete filepath, and read the file in manually after loading the app. You have to copy the file into the standalone folder, at the same level where the mxf is.

To get the full path you need a message box with
;max sendapppath my_send_name

then have a [receive my_send_name] object, that will spit out the complete filepath of the app folder. Just like "path" to [thispatcher] but for an app you have to do it this way. Once you have the filepath (check [sprintf] help file for formatting issues) you can read/write your .json file.

I'm not sure if you need to "include file" when building the standalone if you copy it into the app folder afterwards? does this embed it into the mxf somehow? some of this is a mystery, even after many experiments...

orange_glass's icon

Thanks I'll give it a go, I was just trying to apply this similair https://cycling74.com/forums/pattrstorage-autorestore-and-standalones js solution as I read your post.

My ideal solution would not have a manual click to save/load, I would just like to restore from a single file somewhere on load and have data saved to it when saved. Would I still need these path finding fixes to do this?

I have to admit I'm finding this incredibly difficult for what surely is a common, basic requirement. Is there any improvements in Max 6?

seejayjames's icon

you'll definitely need the path fix for a standalone to make the read-write command to pattrstorage work. this will have to be different (using the ;max command) than in a regular patch ("path" to [thispatcher] in that case). I have it working fine in a recent app I built. Give pattrstorage a moment to load the file before you access its presets (a couple seconds should be more than enough). if it has a "loaded file" report, if so, use that to do your timing.

Building standalones is definitely a bit tricky and there are some things which are still mysterious. Also there are some files you need to add afterwards when using jitter (jitlib.dll etc.), that's messed me up in the past when taking to another computer. I think the docs explain it well though.

orange_glass's icon

Thanks for your help SeeJayJames. I feel like I am almost there now. I have used your commands to successfully obtain the path to the built app and then pass it to read/write commands.

My problem now seems to be that the read command only works once the file has been accessed with a write command. In other words upon opening the app, once I click the read bang nothing happens, however if I save something, edit the textbox data and then read, the textbox returns to its previously saved state, proving that the read/write worked.

Max Patch
Copy patch and select New From Clipboard in Max.

Is there something I'm missing to get the read working straight away?

gbravetti's icon

1) Set "fileusagemode" = 1, for patternstorage.
(also choose a proper "savemode", start with 1 for testing purpouses)

2) If you have already created a .json just move it to another place then reload the .maxpat, it has to load with all pressets blank.

3) Compile your standalone to an empty folder and put the previously moved .json file to that folder

Now your pressets changes will be persistent.

Best!

Ben Carey's icon

Thanks GBRAVETTI for your solution - this works perfectly.

It seems the fileusagemode attribute is designed specifically for the problem that this thread is addressing. Awesome!

Best,

Ben

Florent Ghys's icon

Hello,
same issue here: standalone reads a json file but doesn't write into it...

I am trying your idea GBRAVETTI but it doesn't work here. When you say "put the previously moved .json file to that folder", do you mean to put it in the "Content" folder when right clicking "Show Package Contents" on the app?

Any other ideas?
best
Florent

Florent Ghys's icon

I made it work finally!
GBRAVETTI was right: fileusagemode 1 = do not automatically include the json file while compiling
then add the json file manually into the Content folder in the app (show package contents)
and then messages "store" and "writeagain" do the job!

Shreebz's icon

I'm running into the same issue as OP. GBRAVETTI's solution works well, but is a little nuanced and easy to forget.

Is this still the best way to allow a collective/standalone user to write to a json file?

philip meyer's icon

This thread is great, I'm just going to note down the steps clearly so that others can find it more easily in the future:

1) pattrstorage should use @fileusagemode 1

2) pattrstorage can optionally use @savemode 3 unless you prefer to send writeagain messages to pattrstorage when the pattrstorage JSON/XML should be saved

3) In your .maxpat, use loadbang to trigger (;max sendapppath app_path) to send the application path to a r app_path, then pass this through a sprintf %sYOUR_APP_NAME.app/Contents/PRESET_FILENAME (don't forget to change the application name and the filename, including the extension) and then prepend read and patch into pattrstorage. This will load the preset file that you will store inside the package contents
3a) (Optional) Use route to look for the read message from pattrstorage to trigger actions once the file has been successfully read. Actions may include loading the default preset or populating menus by sending the getslotnamelist message.
4) in your maxpat, remove your presets JSON/XML from the Project folder and clear the pattrstorage
5) Build the standalone

6) Copy the preset file into the Contents folder of the standalone package

standalone_pattrstorage_setup.maxpat
Max Patch