JAMS Technical Discussion

This thread is for reporting issues with the JAMS demo, and or feedback. Keep in mind what system you’re using and any hints at reproducibility! You can tag me @Nigel and @BryanB and we’ll get back to you as soon as we can. Thank you.

5 Likes

I just tried to share a song and but the link was 6500 characters long! Too long for the Discourse PM system

2 Likes

I had this same issue. It’s seems to only be the result of certain songs. I wonder if name length of the artist, jam, album play a factor…

The funky characters encode some simple ASCII text about the artist, title, album, etc, which is compressed then encoded to Base64. That isn’t bad. The biggest factor is going to be the album artwork, which is also included. That is binary data which will not compress well and will make up most of the characters.

6.5 KiB is not bad considering an entire image is encoded. If anyone has recommendations, I’m open to suggestion.

3 Likes

I was originally going to upload album art as ImmutableData and reference the XOR in the song shares. That would certainly cut back on share size.

However, @Nigel would eventually like to show Album art in the Playlists and Library. Fetching the ImmutableData for e.g. every song in the library might not be very friendly for SAFE Network interactions. That wouldn’t be something which could be solved with delayed network fetch or streaming, since one expects all album art to be present, unlike playing the music itself.

Maybe we can figure out some middle ground.

1 Like

I was also wondering what was the song share string composed of, and imagined it should just be the address (xorname) where all the info was already stored (by the user/account that decided to share it).

This is what confused me, so aren’t you already fetching the album art/metadata from the network after you imported a shared song? if so what would be the difference between fetching it from an IM where all the metadata and art is stored than fetching it from one of the account’s/app’s own containers?

1 Like

Have you yet tried fiddling around with uploading a directory?

See this issue that I’ve raised: https://github.com/joshuef/peruse/issues/54

Really curious to know if you hit the same problem.

@bocacho

I’m mixing some ImmutableData and some MutableData, and sharing is different. Specifically, ID uses PlainText/Symmetric/Asymmetric shared via XOR whereas MD uses ??? shared via ???. I looked up MD sharing in the forums and the most recent answer wasn’t convincing (something about one-to-one shares only, no one-to-many currently supported).

so aren’t you already fetching the album art/metadata from the network after you imported a shared song?

All song metadata is MutableData. Someone might want to change the artist, album, song name, etc. @Nigel asked me to make the Album Art replaceable too, which means that is also mutable. All mutable data for a song is stored as a JSON object. The album art is (presently) a ridiculous Base64 encoding of the album’s art as a string, saved to that JSON object. The share is just Base64 encoding of the song’s JSON object. All of one’s song JSON objects are stored into a JSON list. The JSON list represents your Library, which is saved to a single key in the _music container. This reduces calls to the SAFE Network in that your entire Library’s metadata is a single pull. Should it outgrow the space a single value can hold, I might need to shard/segment the library into multiple values, which I have a small plan for.

The song file is not mutable. It won’t get changed. So the mp3 or what-have-you is the only ImmutableData presently used by this application.

I actually have a PDF somewhere (slightly out of date) which shows how I organize my data. I can post that here if people are interested.

Not mentioned above, but Playlists are each unique entries in the _music container. They are simple JSON lists of XORs, and all the metadata for each XOR is pulled from one’s Library. I think one playlist per _music key is wasteful and I’m reconsidering the organization to be more like Library. It might be a single Playlist key which holds multiple playlists as a dictionary of name: xor list.

2 Likes

@hunterlester

All my dev work is local mocknet. I started this back in September/October and probably spent two weeks to a month getting my dev environment up. Brutally honest: I’m still using Web Hosting Manager I built back in 0.6.0 for Mocknet. I updated to Safe Browser 0.7.0 because it was released for Mocknet and worked with my 0.6.0 Web Hosting Manager. The 0.8.0 Browser didn’t work with 0.6.0 Web Hosting Manager (I suspect the MockVault is no longer compatible), but the 0.8.0 Web Hosting Manager was not released with Mocknet support so ¯\(ツ)

I haven’t even touched the Peruse browser. @Nigel brought it to my attention a week or two ago.

Coding at this scale is not conducive with spending time updating all my underlying tools and environment. Now that we hit our first release, I can start looking at updating my environment, fetching latest versions, rebuilding some of those tools for MockNet, etc, before diving into code again.

EDIT: This sounds more snarky than I intended, but I did want to get the point across that staying up to date is a major detriment to making progress with an ambitious or large project on SAFE Net at present. The MockNet releases are a huge boon, but not everything is released that way.

2 Likes

Thanks @BryanB for the explanation, I’m getting you are storing everything within the _music containers itself then.

At a very high level, what I was imagining was that a song’s entire metadata and reference to the actual song’s ImmutableData was stored in a public MD and then you just share the address of that MD to other people (an album could be another MD with its metadata and the reference to all the songs’ MD’s).
Playlists can be personal or also shareable I guess, so you could also keep them in random public MD’s and again just share the xorname.
In any case, it’s up to the user receiving the URL to clone the content or just consume it from the place where it was already stored and shared.

Then the _music container would contain just references to these MD’s, just as an index of the things your app stored on the network.

It sounds like this approach may use more PUT’s when storing the album/songs, but once that’s done, when they are shared, then other users would need to only spend a single insert cost into their own playlist MD with the xorname to be added, and they would automatically see any updates made to the songs’ & albums’ metadata, you could also then enable comments/discussions around a song/album shared among users… Just some thoughts.

4 Likes

@bochaco

Thanks for the feedback. I can see some of the advantages of what you describe, but I’ll have to read it a few times to fully understand it. If you’re the one suggesting it, I’m assuming it’s a pretty darn good idea for the SAFE Network environment :wink:

So if something is in the _public container, it can be easily shared with other people? I understand the ID XOR concept, but with MDs, I’m lost when it comes to sharing MutableData.

EDIT:

In any case, it’s up to the user receiving the URL to clone the content or just consume it from the place where it was already stored and shared.

Is there documentation on this somewhere?

2 Likes

@Nigel FYI if you haven’t read @bochaco’s suggestion, he’s advising we move quite a lot out of the _music container and store it in _public for sharing purposes. This suggestion still makes some light us of _music. What do you think?

I actually didn’t mean in the _public container, but just public MutableData’s (you know you can have public and private MD’s).
So basically it’s just creating them on the network at a random address, ID addresses are calculated based on its content, MD’s on the other hand can be stored at any random address, this is also the reason you’d need to store these addresses in the user’s account, and that’s what I was thinking would be the only info to be stored in the _music container, just MD’s addresses of the songs/albums the user keeps in its own playlists.

Please don’t take this for granted, pros and cons need to be evaluated there and I think it depends on which use cases you wanna support while keeping the PUTs cost low as you seem to be giving some priority/importance for your app.

What I meant was simply that if you shared the address of a song’s/album’s MD, the other user can just read the content from there, he/she doesn’t need to copy that info to be able to play the songs, which BTW opens up the door for another feature which is being able to playback songs without even logging in a safe account, your app’s site can just play it back like youtube does it with a URL you share, so I could just give you this URL: safe://jams.demo/listen?song=fa86f307a28d468c08a64cfe05b87aeff1699f69e827fb7abbbcb86d6f1c3191 and the song could be loaded and played back automatically (I guess you could also support some tiny URLs mechanisms).

6 Likes

I think this is very interesting and indeed would enable some great social sharing features. I especially like the sharing of a tiny URL. So the MD is public and the xor (access to them) is stored encrypted in _music container? If the MD’s are public and then say I Upload “Bohiemien Rhapsody” and send the URL to my friend, they have the xor in their _music container list now BUT if I change the name of the song to “Killer Queen” will that change be reflected to all users that have the xor to that URL in their _music container because I’m the original owner of the MD and changed it?? Could we possibly get the best of both worlds and like you say have the option to “save” or “clone” the MD’s so a user who was shared with can control changes to songs etc within the app? Hopefully I didn’t word that too confusingly. Still trying to fully understand it.

1 Like

There are various ways to do this. My thought was that the share service would have its own MD within _public, like the MD/NFS container for a www service, and then for each shared item an entry is inserted into that MD where the key would be a name (like the path to a file for www). Or maybe there’s a new to level container such as _shares

If the entry value is an immutable address (as with www), I think you might even be able to access those shares as if they were www URIs, in which case the recipient can just paste them into a browser.

If not, or for extra features: short URI, JAMS style shares etc, the entry value would be something else, depending on the content/feature, and the recipient would need to access the share using an app that understands what to do with those entries. If we do this using a service, and somebody :roll_eyes: provides a standard library that supports various services, it becomes easy for any app to support both creation of shares and access of shares (or any number of services, such as LDP storage and other normally server side magic).

If a particular service is sufficiently useful (eg short URIs), then it could be built into the DOM API and/or Peruse by Maidsafe.

I haven’t looked properly at how you are doing things in JAMS yet, but if you want to do anything clever (beyond some standard share service) it should still be possible by implementing it as a custom service. We could work this out together and it could be a new service called jams or something descriptive related to the functions it provides.

The services library is modular, so easy for an app to add its own custom services.

4 Likes

Definitely keep in touch Mark. Be sure to let us know how you progress. I think @bochaco’s solution is very clever but I take heed to his warning as well. It would require a decent amount of change to code likely and as it is the individual user has complete control, just the way we like it. Using a module such as yours to enable this could deliver many of the benefits and show the community collaboration which is very important. Of course the tiny URL is also something that would really enable this kind of sharing in a familiar way to the legacy internet population as well.

7 Likes

I actually didn’t mean in the _public container, but just public MutableData’s (you know you can have public and private MD’s). So basically it’s just creating them on the network at a random address, ID addresses are calculated based on its content, MD’s on the other hand can be stored at any random address, this is also the reason you’d need to store these addresses in the user’s account, and that’s what I was thinking would be the only info to be stored in the _music container, just MD’s addresses of the songs/albums the user keeps in its own playlists.

I definitely missed a few sessions in SafeNet 101.

so I could just give you this URL

Yeah, that’s the thing I need to figure out. Surely there’s something in the MD API to get the URL, but I must have missed it in the past.

I was not aware MDs had URLs. The only URL I can think of is the AuthURI. I’ll need to dive into the API and docs again. I honestly thought MDs not stored in some container disappeared into inky bit blackness

@happybeing

I haven’t looked properly at how you are doing things in JAMS yet, but if you want to do anything clever (beyond some standard share service) it should still be possible by implementing it as a custom service.

I can’t think of anything in the current JAMS app that would be an interesting service for anyone else.

I have, however, written a lot of API layers over layers over layers. One of those layers might be useful to other developers in organizing the code, keeping track of handles, and other things. Updating that code and making it available publicly is on my TODO list. It’s already somewhat available: GitHub - btbonval/maidsafe-test at more_features (safe_api.js is the only file I’ve heavily modified)

EDIT: my favorite piece of code is MD.insert(), where if you haven’t started a Mutation yet, it’s created for you and committed, but if you have an existing Mutation (stored in the state), it’ll add the insert to the existing mutation for a later commit.

2 Likes

I can, playlists for example.

I think the word ‘services’ is misleading in this respect - or rather it isn’t immediately obvious what a service means in a serverless system!

I think I of a SAFE service as a protocol which knows how to do things with a particular type of SAFE storage.

So www takes a URI, accesses a file via an MD that it expects to find has been created with entries in a certain format. It also knows to add ‘index.html’ to the URI if it ends in a ‘/’. It happens that the browser knows how to implement part of the service (retrieval), while the Web Hosting Manager implements storage and retrieval. They both have this behaviour hard coded, but using a services library makes it possible for any app to access www data through a standard RESTful interface. Web servers support this through simple GET/POST etc, WebDav was a standardised service for storage, and the Linked Data Platform (LDP) is yet another - all similar ways of putting and getting data from a Web server through slightly different protocols.

Unfortunately lots of functionality has tended to end up on servers, so these simple protocols have been replaced by complex libraries, and lots of code running on a server to implement them. With SAFE and SOLID, I think the idea is to get back to TimBL’s original vision, have simple RESTful protocols that just know how to store and get data in standard ways such as LDP, and let the client do the manipulation and processing of that data.

This is the separation between data processing (app) and data storage (platform) where the user can choose where to store their data, and which app to use with it.

A Playlist Service

So imagine a playlist service. This would expect some kind of label (really also a URI) and the service knows how these are stored also. So it can save one for you, and if you try and load one, it knows what to do with it - load it into JAMS for example, or another music player you have registered for that service. So if you and others build support for JAMS playlists into your apps, all you need to do is include the services library in your app. This may be best handled in a different way - playlist files on a standard storage device like LDP for example. I’m still trying to understand it myself TBH, but I think it is worth thinking about this so that different apps can more easily store and use data for use with other apps.

At least, this is how I envisage SAFE services working - I don’t think MaidSafe have described this anywhere yet so I’m going out on a limb a bit. We’ll find out soon enough, when I have the LDP service working we can see what they think of it :slight_smile:

I’d be interested to here from Maidsafe where I’m right and where I’m wrong in this, but obvs they are busy and I expect we’ll get into this more when I have some working code.

In the short term I think you and other app devs can ensure a degree of interoperability by sticking close to the SAFE NFS storage model, as used by the Web Hosting Manager, and we can build services on top of that where standard client side processing is useful, such as LDP.

4 Likes

I’ve thought of something similar before but was under the impression that would be a JAMS API. Where another SAFE app could do a JAMS API call for our player, and/or playlist, other possibilities, and it shows up (with some JAMS branding possibly :thinking:), kind of like you know when you see an imbedded YouTube video. I might be wrong on how this is done technically but try to peg down what could be useful with what makes it technically possible. Does this sound close @happybeing?

Also what you mentioned allows people to use any competitor to JAMS or just a slightly different service because it’s their data, which is cool too :sunglasses:

1 Like