How to start and change Synth? - osc

I'm fiddling with SuperCollider + OSC and right now i don't seem to get the proper understanding of it.
This code should do:
start a server
define a synth
start an instance of the synth
mount a listener to alter the sin frequency through remote command
(
Server.default = Server.internal;
s = Server.default;
s.boot;
SynthDef(\fly, { arg freq = 500;
Out.ar(0, SinOsc.ar(freq, 0, 0.1))
}).add;
~fly = Synth.new(\fly);
OSCdef.new(
\move,
{arg msg;
[msg].postln;
~fly.set(\freq, msg[0]);
},
'/move',
nil, 57120
);
)
Obviously it does not work as intented. The synth is not created by running the whole script. I need to run every block by itself. Also the call in OSCDef doesn't know about the ~fly synth: FAILURE IN SERVER /n_set Node 1000 not found.

JITLib makes use of the environment variables and adds a bunch of behavior. If you want to use a plain variable and manage the Synth yourself, use one of the single-character vars [a..z] instead of ~fly. Otherwise, you can let JITLib do its thing, in which case something like this will work:
(
Server.default = Server.internal;
s = Server.default;
s.boot;
~fly = { arg freq = 500;
SinOsc.ar(freq, 0, 0.1)
};
OSCdef.new(
\move,
{arg msg;
[msg].postln;
~fly.set(\freq, msg[0]);
},
'/move',
nil, 57120
);
)
Reference:
http://doc.sccode.org/Overviews/JITLib.html
http://doc.sccode.org/Classes/Environment.html

Related

"Unable to cast to Dictionary" error occurred when trying to tween

I was trying to make a tween for a text so whenever when player loaded and wait for at least 5 seconds after they loaded in, the text transparency will set to 0 smoothly
Then, I tried to make that happen with a service called TweenService but I was greeted with an error "Unable to cast to Dictionary"
I tried another way by checking the documentation and Forums but didn't find or solve any solutions
Here's my code:
local loadingrobloxos = LoadingAssetsGUI.LoadingBootBackground.LoadingRobloxOS
local goallro = loadingrobloxos.TextTransparency == 0
local tweeninfolro = TweenInfo.new(
0.5,
Enum.EasingStyle.Quad,
Enum.EasingDirection.InOut,
1,
false
)
local tweenlro = TweenService:Create(loadingrobloxos, tweeninfolro, goallro):Play()
What is actually wrong?
If you look at the documentation for TweenService:Create, you'll see that the last argument of the function is supposed to be a dictionary.
TweenService:Create(loadingrobloxos, tweeninfolro, goallro)
The error is telling you that whatever you passed in for the variable goallro, it cannot be converted to a dictionary. And that line is...
local goallro = loadingrobloxos.TextTransparency == 0
This line is not creating a dictionary, it is asking the question, "is loadingrobloxos's TextTransparency currently set to zero?" So the variable goallro is set to false. TweenService doesn't know what to do with false, so it throws the error.
Instead, try this :
local goallro = {
TextTransparency = 0
}

Roblox- how to store large arrays in roblox datastores

i am trying to make a game where players create their own buildings and can then save them for other players to see and play on. However, roblox doesn't let me store all the data needed for the whole creation(there are several properties for each brick)
All i get is this error code:
104: Cannot store Array in DataStore
any help would be greatly appreciated!
I'm not sure if this is the best method, but it's my attempt. Below is an example of a table, you can use tables to store several values. I think you can use HttpService's JSONEncode function to convert tables into strings (which hopefully can be saved more efficiently)
JSONEncode (putting brick's data into a string, which you can save into the DataStore
local HttpService = game:GetService("HttpService")
-- this is an example of what we'll convert into a json string
local exampleBrick = {
["Size"] = Vector3.new(3,3,3),
["Position"] = Vector3.new(0,1.5,0),
["BrickColor"] = BrickColor.new("White")
["Material"] = "Concrete"
}
local brickJSON = HttpService:JSONEncode(exampleBrick)
print(brickJSON)
-- when printed, you'll get something like
-- { "Size": Vector3.new(3,3,3), "Position": Vector3.new(0,1.5,0), "BrickColor": BrickColor.new("White"), "Material": "Concrete"}
-- if you want to refer to this string in a script, surround it with two square brackets ([[) e.g. [[{"Size": Vector3.new(3,3,3)... }]]
JSONDecode (reading the string and converting it back into a brick)
local HttpService = game:GetService("HttpService")
local brickJSON = [[ {"Size": Vector3.new(3,3,3), "Position": Vector3.new(0,1.5,0), "BrickColor": BrickColor.new("White"), "Material": "Concrete"} ]]
function createBrick(tab)
local brick = Instance.new("Part")
brick.Parent = <insert parent here>
brick.Size = tab[1]
brick.Position= tab[2]
brick.BrickColor= tab[3]
brick.Material= tab[4]
end
local brickData = HttpService:JSONDecode(brickJSON)
createBrick(brickData) --this line actually spawns the brick
The function can also be wrapped in a pcall if you want to account for any possible datastore errors.
Encoding a whole model into a string
Say your player's 'building' is a model, you can use the above encode script to convert all parts inside a model into a json string to save.
local HttpService = game:GetService("HttpService")
local StuffWeWantToSave = {}
function getPartData(part)
return( {part.Size,part.Position,part.BrickColor,part.Material} )
end
local model = workspace.Building --change this to what the model is
local modelTable = model:Descendants()
for i,v in pairs(modelTable) do
if v:IsA("Part") or v:IsA("WedgePart") then
table.insert(StuffWeWantToSave, HttpService:JSONEncode(getPartData(modelTable[v])))
end
end
Decoding a string into a whole model
This will probably occur when the server is loading a player's data.
local HttpService = game:GetService("HttpService")
local SavedStuff = game:GetService("DataStoreService"):GetDataStore("blabla") --I don't know how you save your data, so you'll need to adjust this and the rest of the scripts (as long as you've saved the string somewhere in the player's DataStore)
function createBrick(tab)
local brick = Instance.new("Part")
brick.Parent = <insert parent here>
brick.Size = tab[1]
brick.Position= tab[2]
brick.BrickColor= tab[3]
brick.Material= tab[4]
end
local model = Instance.new("Model") --if you already have 'bases' for the players to load their stuff in, remove this instance.new
model.Parent = workspace
for i,v in pairs(SavedStuff) do
if v[1] ~= nil then
CreateBrick(v)
end
end
FilteringEnabled
If your game uses filteringenabled, make sure that only the server handles saving and loading data!! (you probably already knew that) If you want the player to save by clicking a gui button, make the gui button fire a RemoteFunction that sends their base's data to the server to convert it to a string.
BTW I'm not that good at scripting so I've probably made a mistake somehwere.. good luck though
Crabway's answer is correct in that the HttpService's JSONEncode and JSONDecode methods are the way to go about tackling this problem. As it says on the developer reference page for the DataStoreService, Data is ... saved as a string in data stores, regardless of its initial type. (https://developer.roblox.com/articles/Datastore-Errors.) This explains the error you received, as you cannot simply push a table to the data store; instead, you must first encode a table's data into a string using JSONEncode.
While I agree with much of Crabway's answer, I believe the function createBrick would not behave as intended. Consider the following trivial example:
httpService = game:GetService("HttpService")
t = {
hello = 1,
goodbye = 2
}
s = httpService:JSONEncode(t)
print(s)
> {"goodbye":2,"hello":1}
u = httpService:JSONDecode(s)
for k, v in pairs(u) do print(k, v) end
> hello 1
> goodbye 2
As you can see, the table returned by JSONDecode, like the original, uses strings as keys rather than numeric indices. Therefore, createBrick should be written something like this:
function createBrick(t)
local brick = Instance.new("Part")
brick.Size = t.Size
brick.Position = t.Position
brick.BrickColor = t.BrickColor
brick.Material = t.Material
-- FIXME: set any other necessary properties.
-- NOTE: try to set parent last for optimization reasons.
brick.Parent = t.Parent
return brick
end
As for encoding a model, calling GetChildren would produce a table of the model's children, which you could then loop through and encode the properties of everything within. Note that in Crabway's answer, he only accounts for Parts and WedgeParts. You should account for all parts using object:IsA("BasePart") and also check for unions with object:IsA("UnionOperation"). The following is a very basic example in which I do not store the encoded data; rather, I am just trying to show how to check the necessary cases.
function encodeModel(model)
local children = model:GetChildren()
for _, child in ipairs(children) do
if ((child:IsA("BasePart")) or (child:IsA("UnionOperation"))) then
-- FIXME: encode child
else if (child:IsA("Model")) then
-- FIXME: using recursion, loop through the sub-model's children.
end
end
return
end
For userdata, such as Vector3s or BrickColors, you will probably want to convert those to strings when you go to encode them with JSONEncode.
-- Example: part with "Brick red" BrickColor.
color = tostring(part.BrickColor)
print(string.format("%q", color))
> "Bright red"
I suggest what #Crabway said, use HttpService.
local httpService = game:GetService("HttpService")
print(httpService:JSONEncode({a = "b", b = "c"}) -- {"a":"b","b":"c"}
But if you have any UserData values such as Vector3s, CFrames, Color3s, BrickColors and Enum items, then use this library by Defaultio. It's actually pretty nice.
local library = require(workspace:WaitForChild("JSONWithUserdata"))
library:Encode({Vector3.new(0, 0, 0)})
If you want a little documentation, then look at the first comment in the script:
-- Defaultio
--[[
This module adds support for encoding userdata values to JSON strings.
It also supports lists which skip indices, such as {[1] = "a", [2] = "b", [4] = "c"}
Userdata support is implemented by replacing userdata types with a new table, with keys _T and _V:
_T = userdata type enum (index in the supportedUserdataTypes list)
_V = a value or table representing the value
Follow the examples bellow to add suppport for additional userdata types.
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Usage example:
local myTable = {CFrame.new(), BrickColor.Random(), 4, "String", Enum.Material.CorrodedMetal}
local jsonModule = require(PATH_TO_MODULE)
local jsonString = jsonModule:Encode(myTable)
local decodedTable = jsonModule:Decode(jsonString)
--]]

How to execute mongo shell command from javascript

In a mongo shell window, I'd like to periodically run a script that will display various stats on the database activity, before displaying the stats, I'd like to clear the screen. There is a "cls" command in the mongo shell, but I am not able to execute it from within the javascript.
function stats () {
while(1) {
cls;
print("display stats");
sleep(5000);
}}
The line with the "cls" is not recognized.
Thank you for any suggestions,
Gary
At the first glance it seemed that you won't be able to do it. According to the docs here: "You cannot use any shell helper (e.g. use , show dbs, etc.) inside the JavaScript file because they are not valid JavaScript.".
One option was to fill the screen with empty lines:
function clearIt () { for(var i = 0; i < 100; i++) { print() } }
clearIt()
However, thanks to #NeilLunn pointing it out there seems to be a solution:
function clearIt () { run('clear') }
clearIt()
This would execute system command which will clear your terminal screen. I don't know how reliable it is (see man clear -> depends if it can figure out how to clear screen) and this works only on POSIX systems. On Windows you would have to replace clear with cls:
function clearIt () { run('cls') }
Additional:
I looked up the source code of mongo shell (src/mongo/shell/linenoise.cpp). Here is how it clears the screen:
void linenoiseClearScreen( void ) {
#ifdef _WIN32
COORD coord = {0, 0};
CONSOLE_SCREEN_BUFFER_INFO inf;
HANDLE screenHandle = GetStdHandle( STD_OUTPUT_HANDLE );
GetConsoleScreenBufferInfo( screenHandle, &inf );
SetConsoleCursorPosition( screenHandle, coord );
DWORD count;
FillConsoleOutputCharacterA( screenHandle, ' ', inf.dwSize.X * inf.dwSize.Y, coord, &count );
#else
if ( write( 1, "\x1b[H\x1b[2J", 7 ) <= 0 ) return;
#endif
}
In case you feel like trying to implement your own screen cleaning function by filling screen with chars.
> help admin
ls([path]) list files
pwd() returns current directory
listFiles([path]) returns file list
hostname() returns name of this host
cat(fname) returns contents of text file as a string
removeFile(f) delete a file or directory
load(jsfilename) load and execute a .js file
run(program[, args...]) spawn a program and wait for its completion
runProgram(program[, args...]) same as run(), above
sleep(m) sleep m milliseconds
getMemInfo() diagnostic
This shows the run and runProgram commands along with some other helpers. The program argument is a string.

How to hide console window of subprocess?

I'm trying to write a very simple program to replace an existing executable. It should munge its arguments slightly and exec the original program with the new arguments. It's supposed to be invoked automatically and silently by a third-party library.
It runs fine, but it pops up a console window to show the output of the invoked program. I need that console window to not be there. I do not care about the program's output.
My original attempt was set up as a console application, so I thought I could fix this by writing a new Windows GUI app that did the same thing. But it still pops up the console. I assume that the original command is marked as a console application, and so Windows automatically gives it a console window to run in. I also tried replacing my original call to _exec() with a call to system(), just in case. No help.
Does anyone know how I can make this console window go away?
Here's my code:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
char* lpCmdLine,
int nCmdShow)
{
char *argString, *executable;
// argString and executable are retrieved here
std::vector< std::string > newArgs;
// newArgs gets set up with the intended arguments here
char const ** newArgsP = new char const*[newArgs.size() + 1];
for (unsigned int i = 0; i < newArgs.size(); ++i)
{
newArgsP[i] = newArgs[i].c_str();
}
newArgsP[newArgs.size()] = NULL;
int rv = _execv(executable, newArgsP);
if (rv)
{
return -1;
}
}
Use the CreateProcess function instead of execve. For the dwCreationFlags paramter pass the CREATE_NO_WINDOW flag. You will also need to pass the command line as a string as well.
e.g.
STARTUPINFO startInfo = {0};
PROCESS_INFORMATION procInfo;
TCHAR cmdline[] = _T("\"path\\to\\app.exe\" \"arg1\" \"arg2\"");
startInfo.cb = sizeof(startInfo);
if(CreateProcess(_T("path\\to\\app.exe"), cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo))
{
CloseHandle(procInfo.hProcess);
CloseHandle(procInfo.hThread);
}
Aha, I think I found the answer on MSDN, at least if I'm prepared to use .NET. (I don't think I'm really supposed to, but I'll ignore that for now.)
System::String^ command = gcnew System::String(executable);
System::Diagnostics::Process^ myProcess = gcnew Process;
myProcess->StartInfor->FileName = command;
myProcess->StartInfo->UseShellExecute = false; //1
myProcess->StartInfo->CreateNowindow = true; //2
myProcess->Start();
It's those two lines marked //1 and //2 that are important. Both need to be present.
I really don't understand what's going on here, but it seems to work.
You need to create a non-console application (i.e. a Windows GUI app). If all this app does is some processing of files or whatever, you won't need to have a WinMain, register any windows or have a message loop - just write your code as for a console app. Of course, you won't be able to use printf et al. And when you come to execute it, use the exec() family of functions, not system().

Simplest way to process a list of items in a multi-threaded manner

I've got a piece of code that opens a data reader and for each record (which contains a url) downloads & processes that page.
What's the simplest way to make it multi-threaded so that, let's say, there are 10 slots which can be used to download and process pages in simultaneousy, and as slots become available next rows are being read etc.
I can't use WebClient.DownloadDataAsync
Here's what i have tried to do, but it hasn't worked (i.e. the "worker" is never ran):
using (IDataReader dr = q.ExecuteReader())
{
ThreadPool.SetMaxThreads(10, 10);
int workerThreads = 0;
int completionPortThreads = 0;
while (dr.Read())
{
do
{
ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
if (workerThreads == 0)
{
Thread.Sleep(100);
}
} while (workerThreads == 0);
Database.Log l = new Database.Log();
l.Load(dr);
ThreadPool.QueueUserWorkItem(delegate(object threadContext)
{
Database.Log log = threadContext as Database.Log;
Scraper scraper = new Scraper();
dc.Product p = scraper.GetProduct(log, log.Url, true);
ManualResetEvent done = new ManualResetEvent(false);
done.Set();
}, l);
}
}
You do not normally need to play with the Max threads (I believe it defaults to something like 25 per proc for worker, 1000 for IO). You might consider setting the Min threads to ensure you have a nice number always available.
You don't need to call GetAvailableThreads either. You can just start calling QueueUserWorkItem and let it do all the work. Can you repro your problem by simply calling QueueUserWorkItem?
You could also look into the Parallel Task Library, which has helper methods to make this kind of stuff more manageable and easier.