Problem with g_file_test in glib - c

Im trying to learn glib/gtk. I wrote little code which prints files in directory and assigns "f" if they are normal files or "d" if they are directory. Problem is with if. It always gets false value and appends "f" to file name.
#include <glib.h>
#include <glib/gstdio.h>
#include <glib/gprintf.h>
int main()
{
GDir* home = NULL;
GError* error = NULL;
gchar* file = "a";
home = g_dir_open("/home/stamp", 0, &error);
while (file != NULL)
{
file = g_dir_read_name(home);
if (g_file_test(file, G_FILE_TEST_IS_DIR))
{
g_printf("%s: d\n", file);
} else {
g_printf("%s: f\n", file);
}
}
}

g_dir_read_name returns just the directory/file name. You need to build full path in order to test it using g_file_test. You can use g_build_filename for that.
int main()
{
GDir* home = NULL;
GError* error = NULL;
gchar* file = "a";
home = g_dir_open("/home/stamp", 0, &error);
while (file != NULL)
{
file = g_dir_read_name(home);
gchar* fileWithFullPath;
fileWithFullPath = g_build_filename("/home/stamp", file, (gchar*)NULL);
if (g_file_test(fileWithFullPath, G_FILE_TEST_IS_DIR))
{
g_printf("%s: d\n", file);
}
else
{
g_printf("%s: f\n", file);
}
g_free(fileWithFullPath);
}
g_dir_close( home );
}

Related

Problem with playing the next song automatically with SDL_Mixer

I have this c program which used to search for the mp3 files of given directory and add the files data to linked list.i use SDL2 for audio handling. so much far i would be able to get the playing of mp3 file and what i'm facing here is that i don't know how to play the next song when the first song is played in the linked list.
Here is my code for the program.
#include <dirent.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "file_handle.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
struct tags
{
const char *artist;
} tags;
Mix_Music *music = NULL;
bool loadmedia(char *filepath);
void play();
void init();
void load_file_directory(char *dir_path);
int main(int argc, char *argv[])
{
char *file_path;
if (argc <= 1)
{
fprintf(stderr, "no arguments provided!\n");
}
else
{
file_path = argv[2];
}
if (file_path)
{
load_file_directory(file_path);
}
init();
int count = 0;
for (struct song *node = head; node; node = node->next)
{
printf("%s\n", node->file_path);
}
for (struct song *node = head; node; node = node->next)
{
printf("%s\n", node->file_path);
printf("count is %d\n", count);
count++;
Mix_Music *song = Mix_LoadMUS(node->file_path);
if (Mix_PlayMusic(song, 1) != 0)
{
printf("something\n");
}
while (!SDL_QuitRequested())
SDL_Delay(250);
Mix_FreeMusic(song);
}
// char *file = argv[1];
// bool status = loadmedia(file);
// if(status){
// printf("%s - %s\n",Mix_GetMusicArtistTag(music),Mix_GetMusicTitleTag(music));
// if(Mix_PlayMusic(music,1)){
// printf("something wrong");
// Mix_FreeMusic(music);
// }
// }
// while(!SDL_QuitRequested())
// SDL_Delay(250);
}
bool loadmedia(char *file_path)
{
bool success = false;
if (file_path)
{
music = Mix_LoadMUS(file_path);
success = true;
}
else
{
printf("File Loaded Failed\n");
}
return success;
}
void init()
{
bool success;
if (SDL_Init(SDL_INIT_AUDIO) < 0)
{
printf("Couldn't initialize SDL: %s\n", SDL_GetError());
success = false;
}
if (Mix_Init(MIX_INIT_MP3) != MIX_INIT_MP3)
{
fprintf(stderr, "could not initialized mixer\n", Mix_GetError());
}
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
{
printf("SDL_mixer could not be initialized %s\n", Mix_GetError());
success = false;
}
}

Why is config_read_file() returning config_false?

I have been using libconfig for config files in a project. When I remove the double quotes from sources by source_to_use, config_read_file() returns config_true and also has a syntax error. The syntax error will cause my getter for the source_to_use option to go to the default case. Also because of this my getter for the source array, will also go to the else case. Could this just be me making a simple syntax error with the libconfig format?
This is the config file I am using:
#config for walld
#colors
colors = TRUE;
source_to_use: "sources";
default:
[
"/home/seth/Pictures/kimi.png"
];
sources:
[
"/home/seth/.walld/persona",
"/home/seth/.walld/image-urls"
];
This is the function I have reading it:
settings* read_config(const char* config_file, const char* home_dir) {
settings* options = malloc(sizeof(settings));
config_t config;
config_setting_t* setting;
const char* source;
int colors;
config_init(&config);
if (config_read_file(&config, config_file) == CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
if (config_lookup_bool(&config, "colors", &colors)) {
options->colors = colors;
}
else {
options->colors = 0;
}
if (config_lookup_string(&config, "source_to_use", &source)) {
//NOP
}
else {
source = "default";
}
setting = config_lookup(&config, source);
if (setting != NULL) {
int count = config_setting_length(setting);
linked_node* entry_point = add_node_to_list(NULL, NULL);
linked_node* current = entry_point;
options->sources = entry_point;
for (int i = 0; i < count; i++) {
char* item = config_setting_get_string_elem(setting, i);
current = add_node_to_list(current, item);
}
}
else {
options->sources = malloc(sizeof(linked_node));
int char_count = snprintf(NULL, 0, "%s%s", home_dir, "/.walld/images");
if (char_count <= 0) {
//tough luck
abort();
}
char* default_folder = malloc(char_count + 1U);
if (default_folder == NULL) {
//tough luck
abort();
}
snprintf(default_folder, char_count + 1U, "%s%s", home_dir, "/.walld/images");
options->sources->image = default_folder;
}
config_destroy(&config);
return options;
}
In your read_config function, your first if is:
if (config_read_file(&config, config_file) == CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
The sense of the if is reversed, so you'll return a NULL if the read of the file is valid.
So, you want to reverse the sense of this if:
if (config_read_file(&config, config_file) != CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
Or you could [probably] use:
if (config_read_file(&config, config_file) == CONFIG_FALSE) {

Saving Custum Paramter with WifiManager & Arduinojson 6

I'm trying to save an additional custom parameter to wifimanager which is the mqtt server address but all codes available in the library and all over the internet are for Arduinojson 5, I tried upgrading to Arduinojson 6 to the best of my ability. The code runs with no issues, however, when I restart the esp, it is gone. For somereason, it is not saved.
#include <FS.h> //this needs to be first, or it all crashes and burns...
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
#define TRIGGER_PIN 16
char mqtt_server[40];
bool shouldSaveConfig = false;
void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; }
WiFiManager wifiManager;
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
void setup() {
Serial.begin(115200);
Serial.println("\n Starting");
pinMode(TRIGGER_PIN, INPUT);
//clean FS, for testing
//SPIFFS.format();
if (SPIFFS.begin()) {
Serial.println("** Mounting file system **");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("** Reading config file **");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, buf.get());
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
strcpy(mqtt_server, doc["mqtt_server"]); //get the mqtt_server <== you need one of these for each param
} else {
Serial.println("** Failed to load json config **");
}
configFile.close();
Serial.println("** Closed file **");
}
}
else {
Serial.println("** Failed to mount FS **");
}
wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&custom_mqtt_server);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
resetbtn();
}
Serial.println("connected...yeey :)");
//read updated parameters
strcpy(mqtt_server, custom_mqtt_server.getValue());
//save the custom parameters to FS
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonDocument doc(1024);
doc["mqtt_server"] = mqtt_server;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
serializeJson(doc, Serial);
serializeJson(doc, configFile);
configFile.close();
//end save
}
}
void loop() {
resetbtn();
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
resetbtn();
}
Serial.println("Connected");
wifiManager.process();
saveParamsCallback();
delay(3000);
}
void resetbtn() { if ( digitalRead(TRIGGER_PIN) == HIGH ) { wifiManager.startConfigPortal("Horray"); Serial.println("connected...yeey :)"); } }
void saveParamsCallback () {
Serial.println("Get Params:");
Serial.print(custom_mqtt_server.getID());
Serial.print(" : ");
Serial.println(custom_mqtt_server.getValue());
}
for same purpose instead of using: serializeJson(doc, configFile);
i'm using this function and for me work pretty well
// for writing
bool writeFile(const char * path, const char * message, unsigned int len){
File file = SPIFFS.open(path, FILE_WRITE);
if(!file){
return false;
}
if(!file.write((const uint8_t *)message, len)){
return false;
}
return true;
}
for reading i'm using this function
// for reading
int readFile(const char * path, char ** text){
// retval int - number of characters in the file
// in case of empty file 0
// in case of directory or not found -1
File file = SPIFFS.open(path);
if(!file || file.isDirectory()){
return -1;
}
int file_lenght = file.size();
*text = (char*) malloc(file_lenght*sizeof(char));
for(int i = 0; i < file_lenght; i++){
(*text)[i] = file.read();
}
return file_lenght;
}
you can use this function in this way:
#define WIFI_credential_filename "/config.json"
char * wifi_credentials;
int file_len = readFile(WIFI_credential_filename, &wifi_credentials);
// at this point "wifi_credentials" is filled with the content of
"/config.json" file
this is my implementation, surely it can be improved but I have tested it and it works

How to fprintf on file with recursive

I'm a newbie with recursion. How do I fopen and fclose a file in a recursive function?
void make(LINK lis, char *name, int flag, FILE *f)
{
if (lis == NULL) {
fclose(f);
}
else {
if (flag == 0) {
FILE *f = fopen(name, "w");
flag = 1;
}
else {
fprintf(f, "CODICE: %d\n", lis->d.codice);
make(lis->next, name, 1, f);
}
}
}
My goal is to recursively write "codice" --> CODE in a file.
Your most immediate problem is that on the first call, you open the file and then return to the main program, without processing anything. Opening the file should be a simple test, not an if-then-else.
void make(LINK lis, char *name, FILE *f)
{
if (!lis) {
fclose(f);
}
else {
if (f) {
f = fopen(name, "w");
}
fprintf(f, "CODICE: %d\n", lis->d.codice);
make(lis->next, name, f);
}
}
}
How do I fopen and fclose a file in a recursive function?
Be sure to do so at the same level of recursion.
Consider first how the nth and first would look separately:
void make_nth(LINK lis, FILE *outf) {
if (lis) {
fprintf(outf, "CODICE: %d\n", lis->d.codice);
make_nth(lis->next, outf);
}
}
void make_1st(LINK lis, const char *name) {
FILE *f = fopen(name, "w");
if (f) {
make_nth(lis, f);
fclose(f);
}
}
// Usage
LINK lis = ...;
make_1st(lis, codice.txt);
Now put that together. Various ways exist to do this.
void make(LINK lis, const char *name, FILE *outf) {
if (name) {
assert(outf == NULL);
FILE *f = fopen(name, "w");
if (f) {
make(lis, NULL, f);
fclose(f);
}
} else {
if (lis) {
fprintf(outf, "CODICE: %d\n", lis->d.codice);
make(lis->next, NULL, outf);
}
}
}
// Usage
LINK lis = ...;
make(lis, codice.txt, NULL);

Finding and checking a file extension

I read the other articles for finding the file extension from a filename in C and I've tried them but the problem is that they don't work correctly.
This is my code :
void optionOne()
{
char filenameSrc[101],filenameDest[101];
strcpy(filenameSrc,"");
do
{
printf("Enter source filename (*.c) : ");
scanf("%s",filenameSrc);
}while (check_file_ext(filenameSrc) != 0);
fflush(stdout);
printf("Enter destination filename : ");
scanf("%s",&filenameDest);
char line[80];
FILE* fp = fopen("data.inp","r");
while(fgets(line,sizeof(line),fp))
{
// do something
}
fclose(fp);
}
and the function check_file_ext :
const char *get_file_ext(const char *filename)
{
const char *dot = strrchr(filename, '.');
if(!dot || dot == filename) return "";
return dot + 1;
}
int check_file_ext(const char* filename)
{
return strcmp(get_file_ext(filename),"c") == 0;
}
The problem is in the check method for the file extension?
Could you tell me where is the problem in the code?
Don't return "", return a pointer to '\0' byte instead:
// gcc -std=c99
#include <stdio.h>
#include <string.h>
static const char*
get_file_ext(const char *filename) {
const char *ext = strrchr(filename, '.');
return (ext && ext != filename) ? ext : (filename + strlen(filename));
}
int main() {
char *files[] = {"a.c", ".a", "a", NULL };
for (char** f = files; *f != NULL; ++f)
printf("ext: '%s'\n", get_file_ext(*f));
}
Note: it ncludes . in the extension for consistency.
Output
ext: '.c'
ext: ''
ext: ''
Reverse condition: do{ ... }while(strcmp(get_file_ext(filename), ".c") != 0);

Resources