diff --git a/lib/dat-share.js b/lib/dat-share.js new file mode 100644 index 00000000..0348791e --- /dev/null +++ b/lib/dat-share.js @@ -0,0 +1,11 @@ +var Dat = require('dat-node') + +module.exports = function (dir, done) { + Dat(dir, function (err, dat) { + if (err) return done(err) + dat.importFiles({watch: true}) + dat.joinNetwork() + var link = 'dat://' + dat.key.toString('hex') + done(null, {dat: dat, link: link}) + }) +} diff --git a/lib/spawn-node.js b/lib/spawn-node.js index 179a4dd1..c8f75c50 100644 --- a/lib/spawn-node.js +++ b/lib/spawn-node.js @@ -1,4 +1,6 @@ var resolveAvailable = require('lib/resolve-available') +var uuid = require('uuid/v1') +var mkdirp = require('mkdirp') var extend = require('xtend') var getBaseName = require('path').basename @@ -17,6 +19,7 @@ module.exports = function (collection, nodeName, index, cb) { var lookup = context.nodeInfo.lookup var info = lookup[nodeName] if (info) { + if (typeof info.action === 'function') return info.action({collection, index, context, fileObject}, cb) var name = (info.name || 'Node') + ' 1' var spawnDescriptor = (typeof info.spawn === 'function') ? info.spawn(context) @@ -26,8 +29,10 @@ module.exports = function (collection, nodeName, index, cb) { var externalDescriptor = (typeof info.external === 'function') ? info.external(context) : info.external - - var path = fileObject.resolvePath(name + '.json') + var rn = uuid().substring(0,5) + var folder = fileObject.resolvePath(rn) + mkdirp.sync(folder) + var path = fileObject.resolvePath(folder + '/index.json') resolveAvailable(path, context.fs, function (err, path) { if (err) return cb && cb(err) var id = collection.resolveAvailable(getBaseName(path, '.json')) diff --git a/nodes/chromatic-chunk/object.js b/nodes/chromatic-chunk/object.js index 130d7333..fb6b4cce 100644 --- a/nodes/chromatic-chunk/object.js +++ b/nodes/chromatic-chunk/object.js @@ -4,6 +4,7 @@ var Observ = require('mutant/value') var Property = require('lib/property') var Slots = require('lib/slots') var TemplateSlot = require('lib/template-slot') +var datShare = require('lib/dat-share') var computed = require('mutant/computed') var lookup = require('mutant/lookup') @@ -40,7 +41,22 @@ function ChromaticChunk (parentContext) { inputs: Property([]), outputs: Property(['output']), params: MutantArray([]), - selectedSlotId: Observ() + selectedSlotId: Observ(), + publish: Property(), + publishedName: Property(), + publishedTags: Property(), + publishedShape: Property(), + publishedUrl: Property() + }) + + obs.publish(value => { + if (!value) return + obs.publishedShape.set(parentContext.shape().join(',')) + var fullPath = parentContext.fileObject.resolvePath('.') + datShare(fullPath, function (err, details) { + if (err) return console.log(err) + obs.publishedUrl.set(details.link) + }) }) obs.slots.onAdd(function (slot) { diff --git a/nodes/chromatic-chunk/view.js b/nodes/chromatic-chunk/view.js index 65abe018..f35c1532 100644 --- a/nodes/chromatic-chunk/view.js +++ b/nodes/chromatic-chunk/view.js @@ -6,6 +6,7 @@ var ParamEditor = require('lib/widgets/param-editor') var Range = require('lib/params/range') var ToggleButton = require('lib/params/toggle-button') var ScaleChooser = require('lib/params/scale-chooser') +var Text = require('lib/params/text') var QueryParam = require('lib/query-param') var renderNode = require('lib/render-node') @@ -44,7 +45,12 @@ function renderChromaticChunk (chunk) { ]), h('h1', 'Params'), - ParamEditor(chunk) + ParamEditor(chunk), + h('h1', 'Publish'), + Text(chunk.publishedName, {placeholder: 'Published Name', size: 15}), + Text(chunk.publishedTags, {placeholder: 'bass,funk', size: 15}), + ToggleButton(chunk.publish, {title: 'publish', offTitle: 'publish'}), + h('div.publishedUrl', chunk.publishedUrl) ]), h('div.slot', [ diff --git a/nodes/dat-chunk/create-dat-node.js b/nodes/dat-chunk/create-dat-node.js new file mode 100644 index 00000000..682605e9 --- /dev/null +++ b/nodes/dat-chunk/create-dat-node.js @@ -0,0 +1,65 @@ +var fs = require('fs') +var url = require('url') +var path = require('path') +var Dat = require('dat-node') +var smalltalk = require('smalltalk') +var mirror = require('mirror-folder') +var ram = require('random-access-memory') + +module.exports = function (collection, index, context, fileObject, cb) { + smalltalk.prompt('Enter Dat url', '', 'dat://').then(function (value) { + var datDetails = url.parse(value) + var datHash = datDetails.hostname + + var folderPath = fileObject.resolvePath(datHash) + fetchDat(datHash, folderPath, function (err) { + var path = fileObject.resolvePath(datHash + '/index.json') + var externalDescriptor = { + node: 'Node 1', + scale: '$global', + node: 'externalChunk', + src: fileObject.relative(path), + id: 'dat ' + datHash.substring(0, 5), + routes: {output: '$default'} + } + var node = collection.insert(externalDescriptor, index) + awaitResolve(node.loaded, function () { + cb && cb(null, node) + }) + }) + }) +} + +function fetchDat(hash, folderPath, cb) { + fs.mkdirSync(folderPath) + Dat(ram, {key: hash, sparse: true}, function (err, dat) { + if (err) return cb(err) + var network = dat.joinNetwork() + network.once('connection', function () { console.log('Connected') }) + dat.archive.metadata.update(function () { + var progress = mirror({fs: dat.archive, name: '/'}, folderPath, function (err) { + if (err) return cb(err) + dat.leaveNetwork() + dat.close(cb) + }) + progress.on('put', function (src) { + console.log('Downloading', src.name) + }) + }) + console.log(`Downloading: ${dat.key.toString('hex')}\n`) + }) +} + + +function awaitResolve (obs, cb) { + if (obs()) { + cb(obs()) + } else { + var release = obs(function (value) { + if (release) { + release() + cb(value) + } + }) + } +} diff --git a/nodes/dat-chunk/index.js b/nodes/dat-chunk/index.js new file mode 100644 index 00000000..a4102903 --- /dev/null +++ b/nodes/dat-chunk/index.js @@ -0,0 +1,12 @@ +var createDatNode = require('./create-dat-node') + +module.exports = { + name: 'dat', + node: 'dat-chunk', + group: 'simpleChunks', + description: 'Load a chunk from dat p2p', + action: (opts, cb) => { + console.log('spwan', opts) + createDatNode(opts.collection, opts.index, opts.context, opts.fileObject, cb) + } +} diff --git a/nodes/triggers-chunk/object.js b/nodes/triggers-chunk/object.js index 0b9845c4..26293dff 100644 --- a/nodes/triggers-chunk/object.js +++ b/nodes/triggers-chunk/object.js @@ -5,6 +5,7 @@ var Property = require('lib/property') var destroyAll = require('lib/destroy-all') var resolve = require('mutant/resolve') var MutantArray = require('mutant/array') +var datShare = require('lib/dat-share') module.exports = TriggersChunk @@ -16,7 +17,22 @@ function TriggersChunk (parentContext) { inputs: Property([]), outputs: Property([]), params: MutantArray([]), - selectedSlotId: Property() + selectedSlotId: Property(), + publish: Property(), + publishedName: Property(), + publishedTags: Property(), + publishedShape: Property(), + publishedUrl: Property() + }) + + obs.publish(value => { + if (!value) return + obs.publishedShape.set(parentContext.shape().join(',')) + var fullPath = parentContext.fileObject.resolvePath('.') + datShare(fullPath, function (err, details) { + if (err) return console.log(err) + obs.publishedUrl.set(details.link) + }) }) context.externalChunk = obs diff --git a/nodes/triggers-chunk/view.js b/nodes/triggers-chunk/view.js index 222176aa..405cc74c 100644 --- a/nodes/triggers-chunk/view.js +++ b/nodes/triggers-chunk/view.js @@ -4,6 +4,7 @@ var computed = require('mutant/computed') var ParamEditor = require('lib/widgets/param-editor') var Range = require('lib/params/range') +var Text = require('lib/params/text') var ToggleButton = require('lib/params/toggle-button') var IndexParam = require('lib/index-param') @@ -30,7 +31,12 @@ function renderTriggersChunk (chunk) { ]) ]), h('h1', 'Params'), - ParamEditor(chunk) + ParamEditor(chunk), + h('h1', 'Publish'), + Text(chunk.publishedName, {placeholder: 'Published Name', size: 15}), + Text(chunk.publishedTags, {placeholder: 'bass,funk', size: 15}), + ToggleButton(chunk.publish, {title: 'publish', offTitle: 'publish'}), + h('div.publishedUrl', chunk.publishedUrl) ]), h('div.slot', [ currentSlotEditor(chunk) diff --git a/package.json b/package.json index 805910c4..7987e368 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "bopper": "~2.11.0", "brace": "~0.8.0", "bulk-require": "~0.2.1", + "dat-node": "^3.5.3", "decibels": "^1.0.0", "deep-equal": "^0.2.1", "ejs": "^2.5.6", @@ -40,6 +41,7 @@ "json-query": "^1.4.0", "make-distortion-curve": "^1.0.0", "micro-css": "~2.0.0", + "mirror-folder": "^2.1.1", "mkdirp": "^0.5.0", "mutant": "^3.20.0", "ncp": "^2.0.0", @@ -53,12 +55,15 @@ "pull-cat": "^1.1.11", "pull-stream": "^3.4.5", "pull-stream-to-stream": "github:mmckegg/pull-stream-to-stream#e436acee18b71af8e71d1b5d32eee642351517c7", + "random-access-memory": "^2.4.0", "readable-blob-stream": "^1.1.0", "scroll-into-view": "~1.3.1", + "smalltalk": "^2.4.1", "strftime": "^0.9.2", "tap-tempo": "~0.0.0", "teoria": "~0.4.0", "through": "~2.3.4", + "uuid": "^3.1.0", "wav": "~1.0.1", "wave-recorder": "^2.3.0", "web-midi": "^2.0.0", diff --git a/styles/chunk-node.mcss b/styles/chunk-node.mcss index 92284b44..e06c0b3a 100644 --- a/styles/chunk-node.mcss +++ b/styles/chunk-node.mcss @@ -7,6 +7,17 @@ ChunkNode { div.options { flex: 1 padding: 8px + + div.publishedUrl { + user-select: text; + word-wrap: normal; + width: 300px; + text-overflow: ellipsis; + font-size: 8px; + color: white; + margin: 3px 1px; + } + } div.slot { @@ -17,4 +28,5 @@ ChunkNode { overflow-y: scroll } -} \ No newline at end of file + +} diff --git a/styles/smalltalk.css b/styles/smalltalk.css new file mode 100644 index 00000000..c2dca955 --- /dev/null +++ b/styles/smalltalk.css @@ -0,0 +1,14 @@ +.smalltalk { + position: absolute; + z-index: 1; + border: 10px solid springgreen; + background: whitesmoke; + padding: 10px; + border-radius: 10px; + margin-left: 40%; + margin-top: 300px; +} + +.smalltalk input { + width: 380px; +}