123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <unistd.h>
- #include <future>
- #include <thread>
- #include <condition_variable>
- #include <mutex>
- #include <atomic>
- #include <vector>
- #include "native_midi/native_midi.h"
- #include "util.h"
- #include "palcfg.h"
- #define CLIPLAYER_EXECUTABLE (which("timidity"))
- struct _NativeMidiSong
- {
- std::thread Thread;
- std::mutex Mutex;
- char *file;
- int pid;
- volatile bool playing;
- bool looping;
- };
- const char* midi_file = "/tmp/sdlpal.temp.mid";
- char* cliplayer = nullptr;
- static char *which(const char *cmd)
- {
- static char path[PATH_MAX] = { '\0' };
- FILE *fp = popen(PAL_va(0, "which %s", cmd), "r");
- if (fp == NULL) {
- return NULL;
- }else{
- if (fgets(path, sizeof(path)-1, fp) != NULL)
- {
- if (path[strlen(path) - 1] == '\n') path[strlen(path) - 1] = '\0';
- if (path[strlen(path) - 1] == '\r') path[strlen(path) - 1] = '\0';
- }
- pclose(fp);
- return path;
- }
- }
- extern "C" int native_midi_detect()
- {
- if (cliplayer)
- {
- free(cliplayer);
- cliplayer = nullptr;
- }
- char *path = (gConfig.pszMIDIClient ? gConfig.pszMIDIClient : CLIPLAYER_EXECUTABLE);
- if (path && access(path,F_OK) == 0)
- {
- cliplayer = strdup(path);
- return 1;
- }
- else
- {
- return 0;
- }
- }
- extern "C" NativeMidiSong *native_midi_loadsong(const char *midifile)
- {
- struct stat st;
- if (0 != stat(midifile, &st)) return NULL;
- auto song = new NativeMidiSong;
- if (NULL == song) return NULL;
- if (NULL == (song->file = new char[strlen(midifile) + 1])) return NULL;
- song->pid = -1;
- song->playing = false;
- song->looping = false;
- strcpy(song->file, midifile);
- return song;
- }
- extern "C" NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw)
- {
- FILE *fp = fopen(midi_file, "wb+");
- if (fp)
- {
- char buf[4096];
- size_t bytes;
- while((bytes = SDL_RWread(rw, buf, sizeof(char), sizeof(buf))) > 0)
- fwrite(buf, sizeof(char), bytes, fp);
- fclose(fp);
- return native_midi_loadsong(midi_file);
- }
- return NULL;
- }
- extern "C" void native_midi_freesong(NativeMidiSong *song)
- {
- if (song)
- {
- if (native_midi_active(song))
- native_midi_stop(song);
- if (song->file) delete []song->file;
- delete song;
- }
- }
- extern "C" void native_midi_start(NativeMidiSong *song, int looping)
- {
- if (!song) return;
- native_midi_stop(song);
- song->playing = true;
- song->looping = looping ? true : false;
- song->Thread = std::move(std::thread([](NativeMidiSong *song)->void {
- while(song->looping)
- {
- auto pid = fork();
- int status;
- if (0 == pid)
- {
- char* args[] = { cliplayer, song->file, NULL };
- if (-1 == execv(cliplayer, args)) exit(-1);
- }
- else if (-1 == pid)
- {
- return;
- }
- song->Mutex.lock();
- song->pid = pid;
- song->Mutex.unlock();
- waitpid(pid, &status, 0);
- }
- song->playing = false;
- }, song));
- }
- extern "C" void native_midi_stop(NativeMidiSong *song)
- {
- if (song)
- {
- song->looping = false;
- song->playing = false;
- if (-1 != song->pid)
- {
- song->Mutex.lock();
- kill(song->pid, SIGTERM);
- song->Mutex.unlock();
- }
- if (song->Thread.joinable())
- song->Thread.join();
- song->Thread = std::move(std::thread());
- }
- }
- extern "C" int native_midi_active(NativeMidiSong *song)
- {
- return (song && song->playing) ? 1 : 0;
- }
- extern "C" void native_midi_setvolume(NativeMidiSong *song, int volume)
- {
- // TODO
- }
- extern "C" const char *native_midi_error(NativeMidiSong *song)
- {
- return "";
- }
|