-
Notifications
You must be signed in to change notification settings - Fork 0
OsTools
The osTools module is orthogonal to the capabilities of the turtle graphics engine. That means that you don't have to initialise turtle for this module to work although it does require a GLFW window for clipboard and cursor functions.
To initialise osTools, pass the argv[0] from your main function (which contains the name of your program as well as path information if the program was executed from a directory outside of where it lives) and a GLFW window:
osToolsInit(argv[0], window);All osTools utilities require the module to be initialised prior to use.
See the turtle article for window creating instructions.
- File Dialog
- Clipboard
- Cursor
- File Utilities
- Serial Ports (windows only)
- TCP Sockets
- Camera (windows only)
The original function of the osTools module was to summon OS specific file dialog prompts that allow a user to select a file or folder and communicate the filepath to the program. To invoke a file dialog, use osToolsFileDialogSave() or osToolsFileDialogOpen().
osToolsFileDialogSave() takes in three arguments. OSTOOLS_FILE_DIALOG_FILE or OSTOOLS_FILE_DIALOG_FOLDER, a prename string which autofills a default filename, and a list of extensions, which can be NULL.
osToolsFileDialogSave(OSTOOLS_FILE_DIALOG_FILE, "", NULL);
list_t *extensions = list_init();
list_append(extensions, (unitype) "txt", 's');
list_append(extensions, (unitype) "csv", 's');
list_append(extensions, (unitype) "json", 's');
list_append(extensions, (unitype) "md", 's');
osToolsFileDialogSave(OSTOOLS_FILE_DIALOG_FILE, "", extensions);The return value of the function is 0 for a successful selection and -1 if the file dialog was closed or cancelled by the user. The full filepath of the user's selection is available as osToolsFileDialog.selectedFilenames -> data[0].s.
if (osToolsFileDialogSave(OSTOOLS_FILE_DIALOG_FILE, "", NULL) != -1) {
printf("Saved to: %s\n", osToolsFileDialog.selectedFilenames -> data[0].s);
}If the extensions argument is NULL, then a global extension list will be used which can be populated by using osToolsFileDialogAddGlobalExtension():
osToolsFileDialogAddGlobalExtension("txt"); // add txt to extension restrictions
osToolsFileDialogAddGlobalExtension("csv"); // add csv to extension restrictions
osToolsFileDialogAddGlobalExtension("json"); // add json to extension restrictionsosToolsFileDialogOpen() takes the same arguments as osToolsFileDialogSave() with one added to the front, which is either OSTOOLS_FILE_DIALOG_SINGLE_SELECT or OSTOOLS_FILE_DIALOG_MULTIPLE_SELECT, which can allow the user to select multiple files to open at once.
osToolsFileDialogOpen(OSTOOLS_FILE_DIALOG_MULTIPLE_SELECT, OSTOOLS_FILE_DIALOG_FILE, "", NULL)The return value of the function is 0 for a successful selection and -1 if the file dialog was closed or cancelled by the user. The full filepath of the user's selection is available as osToolsFileDialog.selectedFilenames -> data[0].s, and if multiple files are allowed and selected, they are in subsequent indices of the osToolsFileDialog.selectedFilenames list.
if (osToolsFileDialogOpen(OSTOOLS_FILE_DIALOG_MULTIPLE_SELECT, OSTOOLS_FILE_DIALOG_FILE, "", NULL) != -1) {
printf("Loaded data from: ");
list_print(osToolsFileDialog.selectedFilenames);
}Clipboard functionality was originally done using OS specific implementation, before I realised that GLFW already provides this abstraction. The functions are now nothing more than GLFW function wrappers.
osToolsClipboardSetText("test345");
printf("Copied \"test345\" to clipboard!\n");
osToolsClipboardGetText();
printf("Pasted \"%s\" from clipboard!\n", osToolsClipboard.text);Cursor functionality is also provided by GLFW but with three additional cursors.
/* choose between
GLFW_ARROW_CURSOR
GLFW_IBEAM_CURSOR
GLFW_CROSSHAIR_CURSOR
GLFW_HAND_CURSOR
GLFW_HRESIZE_CURSOR
GLFW_VRESIZE_CURSOR
GLFW_DLESIZE_CURSOR
GLFW_DRESIZE_CURSOR
GLFW_MOVE_CURSOR
cursors */
osToolsSetCursor(GLFW_IBEAM_CURSOR);You can also use osToolsHideAndLockCursor() and osToolsShowCursor().
There are a number of different functions to query, modify, and read files
You can retrieve the filepath of the executable (where the program is stored on the computer, not where it was run from) by using osToolsFileDialog.executableFilepath. This is useful for referencing files that are at relative locations to the executable even when the program is run from another path (such as when you associate a filetype with an application and then double click a file of that type in windows).
You can list all of the files and folders that is in a specific directory using osToolsFileList(). Keep in mind that this function returns a list where every even index is a string containing a filename (not the fullpath, just the name) and odd indices is an integer of the size of the previous file in bytes (so index 0 is a name and index 1 is the size of index 0).
You can also list all the folders in a directory using osToolsFolderList(). This returns a list of just names, there are no sizes.
And lastly, you can list all files and folders using osToolsFileAndFolderList(). In this case, files will have a size and folders will have a size of -1.
These lists can be free'd with list_free()
You can use osToolsCreateFolder() and osToolsDeleteFolder() to create and delete folders.
You can convert the raw bytes of a file to a C array in memory by memory mapping a file. This is done with osToolsFileMap() where you pass in a filename and a pointer to a uint32_t which will write the size of the file in bytes to the memory pointed to by the pointer. This function will return a heap allocated uint8_t array to memory containing the bytes of the file and will return NULL if the operation failed.
Files can be unmapped by passing the original mapped pointer to osToolsFileUnmap(). This function will return 0 on success and -1 on failure. Note that any changes to the memory will be saved to the disk when this function is called.
uint32_t robertoSize;
uint8_t *roberto = osToolsFileMap("config/roberto.tgl", &robertoSize);
if (roberto != NULL) {
for (uint32_t i = 0; i < robertoSize; i++) {
printf("%X ", roberto[i]);
}
puts("");
osToolsFileUnmap(roberto);
}osTools has a simple CSV parser that converts a CSV file to a list. It's not quite as advanced as excel's parser, but quotes should work though escape characters do not. Your mileage may vary.
There are a few different options for loading CSVs, depending on what type you want the data to be and whether it's organised by row or by column.
osToolsLoadCSVString() loads a CSV file where every entry is a string in the list. You can choose between OSTOOLS_CSV_ROW and OSTOOLS_CSV_COLUMN where the returned list of lists has every list be a row of the CSV or a column.
osToolsLoadCSVDouble() works the same way except that only headers of the CSV are strings and the rest of the elements are doubles.
osToolsLoadCSVInt() where all elements except the headers are integers.
list_t *rowLike = osToolsLoadCSVString("config/test.csv", OSTOOLS_CSV_ROW);
list_t *columnLike = osToolsLoadCSVString("config/test.csv", OSTOOLS_CSV_COLUMN);
if (rowLike != NULL) {
list_print(rowLike);
}
if (columnLike != NULL) {
list_print(columnLike);
}Serial Port support only works on windows. This allows you to send and receive messages over UART, this is useful for communicating with embedded systems.
Use these functions to send and receive data through serial ports
osToolsSerialOpen("COM3", OSTOOLS_BAUD_115200, 100); // name, baud rate, timeout (ms)
uint8_t buffer[8] = {0, 1, 2, 3, 4, 5, 6, 7};
osToolsSerialSend("COM3", buffer, 8); // send buffer through COM3
uint8_t receiveBuffer[8];
osToolsSerialReceive("COM3", receiveBuffer, 8, 100); // receive buffer through COM3 (last argument is timeout in ms)
osToolsSerialClose("COM3");A function osToolsListSerialPorts() also exists to list all detected serial ports. This function returns a list of strings containing the names of the serial ports ([COM3, COM5, COM19, COM22, ...]). Find an example in turtle.c
osTools also supports a limited form of TCP/IP sockets (on both windows and linux), also intended for embedded applications (as in, using the library to connect to an embedded server or client). These features have not been tested with general purpose web connections.
The socket layer is lightly abstracted from the original berkeley sockets interface. Each socket is given a user-defined name (null-terminated string), which is used to reference the socket using the osTools socket functions. Here's an example of a TCP client:
osToolsClientSocketCreate("Client1", OSTOOLS_PROTOCOL_TCP, "127.0.0.1", "6000", 10000); // name, protocol, server address, port, timeout (ms)
osToolsSocketSend("Client1", (uint8_t *) "Hello World\r\n", strlen("Hello World\r\n")); // send buffer through TCP
uint8_t *buffer = calloc(128, 1);
osToolsSocketReceive("Client1", buffer, 128, 10000); // receive buffer through TCP (last argument is timeout in ms)
printf("Received: %s\n", buffer);
free(buffer);
osToolsSocketDestroy("Client1");Here's a simple example of a TCP server:
osToolsServerSocketCreate("Server1", OSTOOLS_PROTOCOL_TCP, "6000"); // host a TCP server on port 6000
while (1) {
osToolsServerSocketListen("Server1", "Client1"); // listen on server, when connection is received create a new socket called "Client1"
osToolsSocketSend("Client1", (uint8_t *) "Hello World\r\n", strlen("Hello World\r\n"));
uint8_t *buffer = calloc(128, 1);
osToolsSocketReceive("Client1", buffer, 128, 1000);
printf("Received: %s\n", buffer);
free(buffer);
osToolsSocketDestroy("Client1");
}Note that the listen function blocks until a client connects (no timeout).
osTools does not support DNS lookup.
osTools for window also includes camera support for USB cameras.