/*
* utils.h
* Copyright (C) 2019 David García Goñi <dagargo@gmail.com>
*
* This file is part of Elektroid.
*
* Elektroid is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Elektroid is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Elektroid. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UTILS_H
#define UTILS_H
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
#include <json-glib/json-glib.h>
#include <inttypes.h>
#include "../config.h"
#define CONF_DIR "~/.config/" PACKAGE
#define LABEL_MAX 256
#define AUDIO_SAMPLE_RATE 48000
#define MAX_BACKEND_FSS (sizeof (gint32) * 8)
#define MAX_BACKEND_STORAGE MAX_BACKEND_FSS
#define debug_print(level, format, ...) if (level <= debug_level) fprintf(stderr, "DEBUG:" __FILE__ ":%d:(%s): " format, __LINE__, __FUNCTION__, ## __VA_ARGS__)
#define error_print(format, ...) fprintf(stderr, "%sERROR:" __FILE__ ":%d:(%s): " format "%s", isatty(fileno(stderr)) ? "\x1b[31m" : "", __LINE__, __FUNCTION__, ## __VA_ARGS__, isatty(fileno(stderr)) ? "\x1b[m" : "")
enum item_type
{
ELEKTROID_NONE = 0,
ELEKTROID_FILE = 'F',
ELEKTROID_DIR = 'D'
};
struct backend;
struct item_iterator;
typedef guint (*iterator_next) (struct item_iterator *);
typedef void (*iterator_free) (void *);
typedef gint (*iterator_copy) (struct item_iterator *, struct item_iterator *,
gboolean);
//name must be filled up always. If no name is available, this can be a string representation of the ID without padding. See set_item_name_from_id function.
//In slot mode, id needs to be filled up and will typically be the MIDI preset number (the id is the filename).
//In default mode (not slot mode), id can be used for any or no purpose. It's still possible to use the id as the filename by using the FS_OPTION_ID_AS_FILENAME option.
//A value of -1 in size will show nothing on the interface. If the size column is not used at all, use FS_OPTION_SHOW_SIZE_COLUMN.
struct item
{
enum item_type type;
gchar name[LABEL_MAX];
gint32 id;
gint64 size;
};
struct item_iterator
{
iterator_next next;
iterator_free free;
//copy is only needed when the FS supports directories. This does not mean that mkdir is supported, as dirs could be just a way to show the data.
iterator_copy copy;
void *data;
struct item item;
};
typedef void (*fs_print_item) (struct item_iterator *, struct backend *);
struct job_control;
typedef void (*job_control_callback) (struct job_control *);
struct job_control
{
gboolean active;
GMutex mutex;
job_control_callback callback;
gint parts;
gint part;
gdouble progress;
void *data;
};
// This contains information taken from from the sample data.
struct sample_info
{
guint32 loopstart;
guint32 loopend;
guint32 looptype;
guint32 samplerate;
guint32 bitdepth;
guint32 channels;
guint32 frames;
};
// This contains the format in which data must be load.
struct sample_params
{
guint32 channels;
guint32 samplerate;
};
struct device_desc
{
guint32 id;
gchar name[LABEL_MAX];
gchar alias[LABEL_MAX];
guint32 filesystems;
guint32 storage;
};
enum sysex_transfer_status
{
WAITING,
SENDING,
RECEIVING,
FINISHED
};
struct sysex_transfer
{
gboolean active;
GMutex mutex;
enum sysex_transfer_status status;
gint timeout; //Measured in ms. -1 is infinite.
gint time;
gboolean batch;
GByteArray *raw;
gint err;
};
struct fs_operations;
typedef gint (*fs_init_iter_func) (struct backend *, struct item_iterator *,
const gchar *);
typedef gint (*fs_path_func) (struct backend *, const gchar *);
typedef gint (*fs_src_dst_func) (struct backend *, const gchar *,
const gchar *);
typedef gint (*fs_remote_file_op) (struct backend *, const gchar *,
GByteArray *, struct job_control *);
typedef gchar *(*fs_get_item_slot) (struct item *, struct backend *);
typedef gint (*fs_local_file_op) (const gchar *, GByteArray *,
struct job_control *);
typedef gchar *(*fs_get_ext) (const struct device_desc *,
const struct fs_operations *);
typedef gchar *(*t_get_upload_path) (struct backend *, struct item_iterator *,
const struct fs_operations *,
const gchar *, const gchar *, gint32 *);
typedef gchar *(*t_get_download_path) (struct backend *,
struct item_iterator *,
const struct fs_operations *,
const gchar *, const gchar *);
typedef gint (*t_sysex_transfer) (struct backend *, struct sysex_transfer *);
// All the function members that return gint should return 0 if no error and a negative number in case of error.
// errno values are recommended as will provide the user with a meaningful message. In particular,
// ENOSYS could be used when a particular device does not support a feature that other devices implementing the same filesystem do.
// rename and move are different operations. If move is implemented, rename must behave the same way. However, t's perfectly
// possible to implement rename without implementing move. This is the case in slot mode filesystems.
struct fs_operations
{
gint32 fs;
guint32 options;
const gchar *name;
const gchar *gui_name;
const gchar *gui_icon;
const gchar *type_ext;
guint32 max_name_len;
fs_init_iter_func readdir;
fs_print_item print_item;
fs_path_func mkdir;
fs_path_func delete;
fs_src_dst_func rename;
fs_src_dst_func move;
fs_src_dst_func copy;
fs_path_func clear;
fs_src_dst_func swap;
fs_remote_file_op download;
fs_remote_file_op upload;
fs_get_item_slot get_slot;
fs_local_file_op save;
fs_local_file_op load;
fs_get_ext get_ext;
t_get_upload_path get_upload_path;
t_get_download_path get_download_path;
};
enum fs_options
{
//Show the audio player.
FS_OPTION_AUDIO_PLAYER = 0x1,
//Allow stereo samples. Only useful if used together with FS_OPTION_AUDIO_PLAYER
FS_OPTION_STEREO = 0x2,
//Every operation will block the remote browser.
FS_OPTION_SINGLE_OP = 0x4,
//Filename is the ID instead of the name. Useful when the device allows different items to have the same name.
FS_OPTION_ID_AS_FILENAME = 0x8,
//In slot mode, dst_dir passed to t_get_upload_path includes the ID, a colon (':') and the system filename.
//Also, as every destination slot is always used, drop is only possible over a concrete slot.
//A DND operation of several items over a slot will behave as dropping the first item over the destination slot and the rest over the following ones.
//Typically used together with FS_OPTION_ID_AS_FILENAME but not necessary.
FS_OPTION_SLOT_STORAGE = 0x10,
//Show column options. Name column is always showed.
FS_OPTION_SHOW_ID_COLUMN = 0x20,
FS_OPTION_SHOW_SIZE_COLUMN = 0x40,
FS_OPTION_SHOW_SLOT_COLUMN = 0x80,
//Sort items options.
FS_OPTION_SORT_BY_ID = 0x100,
FS_OPTION_SORT_BY_NAME = 0x200
};
extern int debug_level;
gchar *debug_get_hex_data (gint, guint8 *, guint);
gchar *debug_get_hex_msg (const GByteArray *);
gchar *chain_path (const gchar *, const gchar *);
void remove_ext (gchar *);
const gchar *get_ext (const gchar *);
gchar get_type_from_inventory_icon (const gchar *);
gchar *get_expanded_dir (const gchar *);
gchar *get_local_startup_path (const gchar *);
void free_msg (gpointer);
/**
* Returns the filename for an item, which is a string that uniquely idenfifies an item.
* In a PC, filenames are typically strings but in embedded devices this could be just a number (in string format).
* Typically, in these systems, several slots can have the same name but the id is an address to a memory slot.
* @param options The options member in the fs_operations struct.
* @param item
*/
gchar *get_filename (guint32 options, struct item *item);
guint next_item_iterator (struct item_iterator *);
void free_item_iterator (struct item_iterator *);
gint copy_item_iterator (struct item_iterator *, struct item_iterator *,
gboolean);
gint load_file (const char *, GByteArray *, struct job_control *);
gint save_file (const char *, GByteArray *, struct job_control *);
gint save_file_char (const gchar *, const guint8 *, ssize_t);
gchar *get_human_size (gint64, gboolean);
void set_job_control_progress (struct job_control *, gdouble);
void set_job_control_progress_no_sync (struct job_control *, gdouble);
gboolean file_matches_extensions (const gchar *, gchar **);
gboolean iter_matches_extensions (struct item_iterator *, gchar **);
#endif