I'm trying to get my audio track to play using FMOD but I keep getting an unhandled exception and then it says there's no source code available, and shows me disassembly code.
main.cpp
bool AudioProject::initAudio()
{
// Audio code
fmSound = new Sound();
fmSound->initialise();
fmSound->load("Music/Rocky_Theme_Tune.mp3");
fmSound->play();
return true;
}
I put break points in the see where it stopped, which was in the initialise function. It even goes into the initialise function and then just randomly breaks. I think I have every include file for fmod as I used it last year no problem.
I'll post my sound.h/.cpp files too.
.h
#include "stdafx.h"
#pragma once
#include "fmod.hpp"
#include "fmod.h"
class Sound
{
private:
bool on; //is sound on?
bool possible; //is it possible to play sound?
char * currentSound; //currently played sound
//FMOD-specific stuff
FMOD_RESULT result;
FMOD_SYSTEM * fmodsystem;
FMOD_SOUND * sound;
FMOD_CHANNEL * channel;
public:
Sound();
~Sound();
void initialise (void);
void setVolume (float v);
void load (const char * filename);
void unload (void);
void play (bool pause = false);
bool getSound (void);
void setPause (bool pause);
void setSound (bool sound);
void toggleSound (void);
void togglePause (void);
};
.cpp
#include "stdafx.h"
#include "Sound.h"
#include "fmod.h"
#include "fmod.hpp"
Sound::Sound()
{
on = true; //is sound on?
possible = true; //is it possible to play sound?
currentSound=""; //currently played sound
sound=0;
}
Sound::~Sound()
{
}
//initialises sound
void Sound::initialise (void)
{
//create the sound system. If fails, sound is set to impossible
result = FMOD_System_Create(&fmodsystem);
if (result != FMOD_OK)
possible = false;
//if initialise the sound system. If fails, sound is set to impossible
if (possible)
result = FMOD_System_Init(fmodsystem,2, FMOD_INIT_NORMAL, 0);
if (result != FMOD_OK)
possible = false;
//sets initial sound volume (mute)
if (possible)
FMOD_Channel_SetVolume(channel,1.0f);
}
//sets the actual playing sound's volume
void Sound::setVolume (float v)
{
if (possible && on && v >= 0.0f && v <= 1.0f)
{
FMOD_Channel_SetVolume(channel,v);
}
}
//loads a soundfile
void Sound::load (const char * filename)
{
currentSound = (char *)filename;
if (possible && on)
{
result = FMOD_Sound_Release(sound);
result = FMOD_System_CreateStream(fmodsystem,currentSound, FMOD_SOFTWARE, 0, &sound);
if (result != FMOD_OK)
possible = false;
}
}
//frees the sound object
void Sound::unload (void)
{
if (possible)
{
result = FMOD_Sound_Release(sound);
}
}
//plays a sound (no argument to leave pause as dafault)
void Sound::play (bool pause)
{
if (possible && on)
{
result = FMOD_System_PlaySound(fmodsystem,FMOD_CHANNEL_FREE, sound, pause, &channel);
FMOD_Channel_SetMode(channel,FMOD_LOOP_NORMAL);
}
}
//toggles sound on and off
void Sound::toggleSound (void)
{
on = !on;
if (on == true)
{
load(currentSound);
play();
}
if (on == false)
{
unload();
}
}
//pause or unpause the sound
void Sound::setPause (bool pause)
{
FMOD_Channel_SetPaused (channel, pause);
}
//turn sound on or off
void Sound::setSound (bool s)
{
on = s;
}
//toggle pause on and off
void Sound::togglePause (void)
{
FMOD_BOOL p;
FMOD_Channel_GetPaused(channel,&p);
FMOD_Channel_SetPaused (channel,!p);
}
//tells whether the sound is on or off
bool Sound::getSound (void)
{
return on;
}
Hit a brick wall here, anyone have any ideas?
You are calling FMOD_Channel_SetVolume(channel,1.0f) in initialise, but the channel variable isn't hasn't been initialized yet, it gets initialized by the FMOD_System_PlaySound(fmodsystem,FMOD_CHANNEL_FREE, sound, pause, &channel); in Sound::play
Related
I am writing a program that needs to play a lot of synthesized sine waves in rapid succession. I am using C++ and SFML to write this program. I have created a class to represent a synthesizer. It is responsible for generating the sine wave and playing it down a single audio stream. However, whenever I use the app, I get a lot of crackling and popping sounds that get intermixed in. I am not sure if this is a library issue or I am generating and feeding in the sine wave wrong. Here is my code:
synth.h
#pragma once
#include <SFML/Audio.hpp>
#include <vector>
#include <mutex>
class Synth : public sf::SoundStream {
std::vector<sf::Int16> m_AudioData;
std::mutex m_Lock;
bool m_ClearData, m_Loaded, m_Started;
int m_Amplitude;
const float TAU = 6.28318;
public:
Synth(int);
Synth(const Synth&);
~Synth();
bool onGetData(sf::SoundStream::Chunk&) override;
void onSeek(sf::Time) override;
void makeSound(float, int);
bool busy();
};
synth.cpp
#include "synth.h"
Synth::Synth(int amplitude)
: m_Amplitude(amplitude)
, m_Loaded(false)
, m_ClearData(false)
, m_Started(false)
{
initialize(1, 44100);
}
Synth::Synth(const Synth& other)
: m_Amplitude(other.m_Amplitude)
, m_Loaded(false)
, m_ClearData(false)
, m_Started(false)
{
initialize(1, 44100);
}
Synth::~Synth() {
stop();
}
bool Synth::onGetData(Chunk &chunk) {
static const sf::Int16 empty[10] = { 0 };
m_Lock.lock();
if (m_Loaded) {
chunk.sampleCount = m_AudioData.size();
chunk.samples = m_AudioData.data();
m_ClearData = true;
m_Loaded = false;
}
else {
if (m_ClearData) {
m_AudioData.clear();
m_ClearData = false;
}
chunk.sampleCount = 10;
chunk.samples = empty;
}
m_Lock.unlock();
return true;
}
void Synth::onSeek(sf::Time) {}
void Synth::makeSound(float freq, int duration) {
m_Lock.lock();
m_ClearData = false;
m_Loaded = true;
m_AudioData.clear();
int sampleCount = duration * 44;
int amplitude = m_Amplitude;
for (int i = 0; i < sampleCount; i++) {
if (i < sampleCount / 5)
amplitude = floor(m_Amplitude * (i / (double)sampleCount) * 5);
else if (i > sampleCount / 2)
amplitude = floor(m_Amplitude * ((sampleCount - i) / (double)sampleCount));
else
amplitude = m_Amplitude;
m_AudioData.push_back(amplitude * sin(TAU * (freq / 44100) * i));
}
m_Lock.unlock();
if (!m_Started) {
play();
m_Started = true;
}
}
bool Synth::busy() {
bool isBusy = false;
if (m_Lock.try_lock()) {
isBusy = m_Loaded || m_ClearData;
m_Lock.unlock();
}
return isBusy;
}
For context, these synthesizers are stored in a vector owned by a parent class. They are used to represent available channels for playing audio. There are 50 stored in the parent class in total, however the number can vary. I doubt that this has any relevance to my problem, but I wanted to inform everyone to the best of my ability.
Thanks a million, open to any other side criticisms of my code.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I write a program to capture the packets using Library "Winpcap". ( How to complie WinPcap with VS2010? Please see this link: http://www.rhyous.com/2011/11/12/how-to-compile-winpcap-with-visual-studio-2010/)
I want to capture the packet(using pcap_loop()) and at the same time I process the packet in the same function void D. The code int x = 1; in function void D is only an easy example which represents some functions that can process the packet. The thread t calls void D. The thread tt calls the function startCap() which captures the packet.
I want to emphasize my question: I debug the program and it stops at the position of pcap_loop() in thread tt until pcap_loop() finishes. I set the parameter of pcap_loop() to make it to run without end because I need continious capture of packet. The result is that the program will not go to the next step int x = 1;. I want to run int x = 1; as thread tt runs. In a word, I wish that the both threads t and tt run at the same time. But the program runs only on thread tt without jumping out and run on thread t.
PS 1: int x = 1; keeps staying better in void D.
PS 2: There's no erros in compiling and debuging. But the program falls into the function pcap_loop which is in the thread tt.
Did I make my question clear?
The whole code:
Data.h
#ifndef DATA_H
#define DATA_H
#include <pcap/pcap.h>
#include <vector>
using namespace std;
struct PcapDevice
{
string name;
string description;
};
class Data
{
public:
Data();
~Data();
bool findDevices(vector<PcapDevice> &deviceList );
bool openDevices(const char * device);
void processPacket();
void startCap();
private:
pcap_t* inData;
char errbuf[256];
bool isCapturing;
pcap_if_t * m_pDevs;
};
#endif // DATA_H
Data.cpp
#include "Data.h"
#include <iostream>
// define pcap callback
void capture_callback_handler(unsigned char *userData, const struct pcap_pkthdr* pkthdr, const unsigned char * packet)
{
((Data*) userData)->processPacket();
}
Data::Data()
{
memset(errbuf,0,PCAP_ERRBUF_SIZE);
isCapturing = false;
inData = NULL;
m_pDevs = NULL;
}
Data::~Data()
{
}
// process the packet
void Data::processPacket()
{
return ;
}
// find local adapter
bool Data::findDevices(vector<PcapDevice> &deviceList )
{
m_pDevs = NULL;
int res = pcap_findalldevs(&m_pDevs, errbuf);
if(0 == res)
{
pcap_if_t * pIter = m_pDevs;
while(pIter != NULL)
{
PcapDevice device;
device.description = pIter->description;
device.name = pIter->name;
deviceList.push_back(device);
pIter = pIter->next;
}
return true;
}
else
{
printf("PCAP: no devices found\n");
}
return false;
}
// open the adapter
bool Data::openDevices(const char *device)
{
if ( (inData = pcap_open_live(device, 8192, 1, 512, errbuf)) == NULL)
{
return false;
}
return true;
}
// start the process of capturing the packet
void Data::startCap()
{
if ( inData == NULL ){
fprintf(stderr, "ERROR: no source set\n" );
return;
}
// free the list of device(adapter)
pcap_freealldevs(m_pDevs);
Data* data = this;
isCapturing = true;
// capture in the loop
if ( pcap_loop(inData, -1, capture_callback_handler, (unsigned char *) data) == -1)
{
fprintf(stderr, "ERROR: %s\n", pcap_geterr(inData) );
isCapturing = false;
}
}
main.cpp
#include <WinSock2.h>
#include <Windows.h>
#include <time.h>
#include "Data.h"
#include <boost\thread\thread.hpp>
#include <boost\function.hpp>
struct parameter
{
Data* pData;
};
void D(void* pParam)
{
// init the parameter
parameter* pUserParams = (parameter*)pParam;
boost::function<void()> f;
// the capture thread will be started
f = boost::bind(&Data::startCap, pUserParams->pData);
boost::thread tt(f);
tt.join();
// I want to work on the packet at the same time, the code "int x=1" is only an easy example
// and it represents a series of functions that can process the packet. I want to run those function as the thread tt runs.
int x = 1;
}
void main()
{
Data oData;
parameter pPara ;
pPara.pData = &oData;
std::vector<PcapDevice> DevList;
oData.findDevices(DevList);
int num = DevList.size()-1;
oData.openDevices(DevList[num].name.c_str());
boost::thread t(D,(void*)&pPara);
t.join();
}
Calling tt.join() will wait until the thread finishes (that is, startCap() returns) before executing the next statement.
You can simply put your int x = 1; before the join(); however, the thread may have not have even started at that point. If you want to ensure the thread is running, or up to a certain point before processing int x = 1; you can use a condition_variable:
The condition_variable class is a synchronization primitive that can be used to block a thread, or multiple threads at the same time, until:
a notification is received from another thread
void Data::startCap(std::condition_variable& cv)
{
if ( inData == NULL ){
fprintf(stderr, "ERROR: no source set\n" );
return;
}
// free the list of device(adapter)
pcap_freealldevs(m_pDevs);
Data* data = this;
isCapturing = true;
// Notify others that we are ready to begin capturing packets
cv.notify_one();
// capture in the loop
if ( pcap_loop(inData, -1, capture_callback_handler, (unsigned char *) data) == -1)
{
fprintf(stderr, "ERROR: %s\n", pcap_geterr(inData) );
isCapturing = false;
}
}
void D(void* pParam)
{
// init the parameter
parameter* pUserParams = (parameter*)pParam;
// Create conditional_variable
std::conditional_variable cv;
// Pass the conditional_variable by reference to the thread
boost::thread tt(&Data::startCap, pUserParams->pData, std::ref(cv));
// Wait until the thread notifies us it's ready:
cv.wait();
// Process packets etc.
int x = 1;
// Wait for the thread to finish
tt.join();
}
Now D() will start the thread tt and then wait until startCaps has reached a certain point (where it calls notify_one()) before we continuing doing things.
I am trying to setup simple PIO access to my hard drive but I've hit a wall on the very first step towards the goal.
First step to working with ATA device is to read it's state register and wait until it's BSY (7th) bit is low. I've got the program doing that, but for some reason when reading the state register it always gives me 0xFF instead. Here is the program sample written in C++:
#include <stdio.h>
#include <stdlib.h>
#include <sys/io.h>
#define DRDY_OFFSET 6
#define BSY_OFFSET 7
const int STATE[2] = { 0x1F7, 0x177 };
bool requestPrivilege() {
if (iopl(3) == -1) {
printf("Unable to request privilege level III. Exiting.\n");
exit(1);
}
}
bool wait(auto lambda) {
int maxAttempts = 30 * 1000;
while((maxAttempts--)) {
if (lambda()) return true;
}
return false;
}
bool waitIdle(int channel) {
auto lambda = [=]() -> bool {
printf("%x\n", inb_p(STATE[channel]));
return !(inb_p(STATE[channel]) & (1 << BSY_OFFSET));
};
return wait(lambda);
}
bool waitReady(int channel) {
auto lambda = [=]() -> bool {
return inb_p(STATE[channel]) & (1 << DRDY_OFFSET);
};
return wait(lambda);
}
int main() {
requestPrivilege();
if (!waitIdle(0)) {
printf("BSY waiting timeout.\n");
exit(1);
};
if (!waitReady(0)) {
printf("DRDY waiting timeout.\n");
exit(1);
};
// //
// DO SOMETHING WITH READY DEVICE HERE //
// //
return 0;
}
Would you please look at the snippet and tell me what's wrong?
Here is a sample of the main code ("Library/stack.h" doesn't really matter, but in any case, it is the last source included in this previous question of mine):
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <tinythread.h>
#include "Library/stack.h"
using namespace std;
using namespace tthread;
#define BOULDERspd 100
// ========================================================================= //
struct Coord {
int x, y;
};
int randOneIn (float n) {
return ((int) (n * (rand() / (RAND_MAX + 1.0))));
}
int randOneIn (int n) {
return ((int) ((float) n * (rand() / (RAND_MAX + 1.0))));
}
// ========================================================================= //
#include <windows.h>
void gotoxy (int column, int line) {
if ((column >= 0) && (line >= 0)) {
COORD coord;
coord.X = column;
coord.Y = line;
SetConsoleCursorPosition(
GetStdHandle( STD_OUTPUT_HANDLE ),
coord
);
}
}
void gotoxy (Coord pos) {
gotoxy(pos.x, pos.y);
}
// ========================================================================= //
void render (char image, Coord pos) {
gotoxy(pos);
cout << image;
}
void unrender (Coord pos) {
gotoxy(pos);
cout << ' ';
}
// ========================================================================= //
char randimage (void) {
return (rand() % 132) + 123;
}
mutex xylock;
class Boulder {
char avatar;
Coord pos;
public:
Boulder (int inix) {
pos.x = inix;
pos.y = 0;
avatar = randimage();
};
void fall (void) {
unrender(pos);
pos.y++;
render(avatar, pos);
Sleep(BOULDERspd);
};
void live (void) {
do {
fall();
} while (y() < 20);
die();
};
void die (void) {
unrender(pos);
pos.y = 0;
};
int x (void) { return pos.x; };
int y (void) { return pos.y; };
};
// ========================================================================= //
class thrStack: public Stack<thread*> {
public:
thrStack (): Stack<thread*> () { };
void pushNrun (thread* elem) {
push(elem);
top->core->joinable();
}
};
void randBoulder (void* arg) {
srand(time(NULL));
Boulder boulder(rand() % 40);
boulder.live();
}
void Boulders (void* arg) {
srand(time(NULL));
thrStack stack;
do {
stack.pushNrun(new thread (randBoulder, 0));
Sleep(rand() % 300);
} while(1);
}
// ========================================================================= //
// ========================================================================= //
int main() {
thread raining (Boulders, 0);
raining.join();
}
I'm new to multi-threading so, to fiddle around with it, I'm trying to make a program that makes random characters constantly fall from the top of the screen, as if it were raining ASCII symbols.
I've noticed, however, a little (big) error in my coding:
bool xylock = false;
class Boulder {
char avatar;
Coord pos;
public:
Boulder (int inix) {
pos.x = inix;
pos.y = 0;
avatar = randimage();
};
void fall (void) {
unrender(pos);
pos.y++;
render(avatar, pos);
Sleep(BOULDERspd);
};
void live (void) {
do {
fall();
} while (y() < 20);
die();
};
void die (void) {
unrender(pos);
pos.y = 0;
};
int x (void) { return pos.x; };
int y (void) { return pos.y; };
};
Because the fall() function uses gotoxy, which changes the 'global cursor', multiple calls to gotoxy would mess up the intended execution of the program. If you try to compile the code as-is, you'd get falling letters that constantly switch position and leave garbage of themselves behind.
Is there any way to use or implement a lock for this and future situations alike with just TinyThread? What is the logic of locks implementing in C++, in general?
EDIT: Modified fall(); is it okay, Caribou?
void fall (void) {
lock_guard<mutex> guard(xylock);
unrender(pos);
pos.y++;
render(avatar, pos);
xylock.unlock();
Sleep(BOULDERspd);
};
You can use the tinythread lib:
http://tinythreadpp.bitsnbites.eu/doc/
Look specifically at lock_guard and mutex
multiple calls to gotoxy would mess up the intended execution of the
program. If you try to compile the code as-is, you'd get falling
letters that constantly switch position and leave garbage of
themselves behind.
create a mutex object to synchronise on, and then in the function you want to be thread safe you create a local lock_guard using it. This mutex can be used in multiple places as well using the lock_guard.
Here I created a very basic threading example without a framework or classes. As you can see, threading and syncronisation isn't C++ work, it's OS work! ;-)
Here I created a simple threadfunction, which I call two times. The threads writing the same variable, but can't do that the same time, so have to protect it. In this sample I use a CRITICAL_SECTION object to lock the variable by one thread. If the one thread lock it, the other can't access it and have to wait until it's free.
Have a closer look and see, I also protected the printf operations. What would happen if you don't do this? You will get a very funny outprint! Find out why and you know how threads and locks work. :-)
#include <windows.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <process.h>
//a global variable (just do do someting):
int g_ThreadCounter = 0;
//global variable to end the threads:
bool g_Run = true;
//do not use global variables, there are better solutions! I just did it here to
//keep it simple and focus on the issue!
//a critical section object - something like a "soft-version" of a mutex to synchronize
//write access on variables
CRITICAL_SECTION critical;
//a thread function
unsigned __stdcall threadFunc(void *pThreadNum)
{
unsigned int iThreadNum = reinterpret_cast<unsigned int>(pThreadNum);
do{
//you need the critical section only when you change values:
EnterCriticalSection(&critical);
g_ThreadCounter++;
printf("from thread: ");
printf("%d", iThreadNum);
printf(" counter = ");
printf("%d", g_ThreadCounter);
printf("\n");
LeaveCriticalSection(&critical);
//sleep a secound
Sleep (1000);
}while(g_Run);
_endthreadex(0);
return 0;
}
int main()
{
unsigned int ThreadID1 = 1;
unsigned int ThreadID2 = 2;
//initialize the critical section with spin count (can be very effective in case
//of short operation times, see msdn for more information)
if(!InitializeCriticalSectionAndSpinCount(&critical, 1000))
{
//DO NOT START THE THREADS, YOU DON'T HAVE SYNCHRONISATION!!!
printf("someting went wrong, press any key to exit");
//do some error handling
getchar();
exit(-1);
}
//start the threads
HANDLE thHandle1 = (HANDLE)_beginthreadex(NULL, 0, &threadFunc, (void*) ThreadID1, 0, NULL);
HANDLE thHandle2 = (HANDLE)_beginthreadex(NULL, 0, &threadFunc, (void*) ThreadID2, 0, NULL);
if(thHandle1 == INVALID_HANDLE_VALUE || thHandle2 == INVALID_HANDLE_VALUE)
{
printf("something went wrong, press any key to exit");
//do some error handling
getchar();
exit(-1);
}
//the main thread sleeps while the other threads are working
Sleep(5000);
//set the stop variable
EnterCriticalSection(&critical);
g_Run = false;
LeaveCriticalSection(&critical);
//wait for the thread; infinite means, you wait as long as the
//thread takes to finish
WaitForSingleObject(thHandle1, INFINITE);
CloseHandle(thHandle1);
WaitForSingleObject(thHandle2, INFINITE);
CloseHandle(thHandle2);
DeleteCriticalSection(&critical);
printf("press any key to exit");
getchar();
return 0;
}
Study the OS on which you are working! It's sometimes better than pay too much attention on Frameworks and foreign classes. This can solve a lot of questions!
I am reading a message from a socket with C++ code and am trying to plot it interactively with matplotlib, but it seems Python code will block the main thread, no matter I use show() or ion() and draw(). ion() and draw() won't block in Python.
Any idea how to plot interactively with matplotlib in C++ code?
An example would be really good.
Thanks a lot.
You may also try creating a new thread that does the call to the
blocking function, so that it does not block IO in your main program
loop. Use an array of thread objects and loop through to find an unused
one, create a thread to do the blocking calls, and have another thread
that joins them when they are completed.
This code is a quick slap-together I did to demonstrate what I mean about
using threads to get pseudo asynchronous behavior for blocking functions...
I have not compiled it or combed over it very well, it is simply to show
you how to accomplish this.
#include <pthread.h>
#include <sys/types.h>
#include <string>
#include <memory.h>
#include <malloc.h>
#define MAX_THREADS 256 // Make this as low as possible!
using namespace std;
pthread_t PTHREAD_NULL;
typedef string someTypeOrStruct;
class MyClass
{
typedef struct
{
int id;
MyClass *obj;
someTypeOrStruct input;
} thread_data;
void draw(); //Undefined in this example
bool getInput(someTypeOrStruct *); //Undefined in this example
int AsyncDraw(MyClass * obj, someTypeOrStruct &input);
static void * Joiner(MyClass * obj);
static void * DoDraw(thread_data *arg);
pthread_t thread[MAX_THREADS], JoinThread;
bool threadRunning[MAX_THREADS], StopJoinThread;
bool exitRequested;
public:
void Main();
};
bool MyClass::getInput(someTypeOrStruct *input)
{
}
void MyClass::Main()
{
exitRequested = false;
pthread_create( &JoinThread, NULL, (void *(*)(void *))MyClass::Joiner, this);
while(!exitRequested)
{
someTypeOrStruct tmpinput;
if(getInput(&tmpinput))
AsyncDraw(this, tmpinput);
}
if(JoinThread != PTHREAD_NULL)
{
StopJoinThread = true;
pthread_join(JoinThread, NULL);
}
}
void *MyClass::DoDraw(thread_data *arg)
{
if(arg == NULL) return NULL;
thread_data *data = (thread_data *) arg;
data->obj->threadRunning[data->id] = true;
// -> Do your draw here <- //
free(arg);
data->obj->threadRunning[data->id] = false; // Let the joinThread know we are done with this handle...
}
int MyClass::AsyncDraw(MyClass *obj, someTypeOrStruct &input)
{
int timeout = 10; // Adjust higher to make it try harder...
while(timeout)
{
for(int i = 0; i < MAX_THREADS; i++)
{
if(thread[i] == PTHREAD_NULL)
{
thread_data *data = (thread_data *)malloc(sizeof(thread_data));
if(data)
{
data->id = i;
data->obj = this;
data->input = input;
pthread_create( &(thread[i]), NULL,(void* (*)(void*))MyClass::DoDraw, (void *)&data);
return 1;
}
return 0;
}
}
timeout--;
}
}
void *MyClass::Joiner(MyClass * obj)
{
obj->StopJoinThread = false;
while(!obj->StopJoinThread)
{
for(int i = 0; i < MAX_THREADS; i++)
if(!obj->threadRunning[i] && obj->thread[i] != PTHREAD_NULL)
{
pthread_join(obj->thread[i], NULL);
obj->thread[i] = PTHREAD_NULL;
}
}
}
int main(int argc, char **argv)
{
MyClass base;
base.Main();
return 0;
}
This way you can continue accepting input while the draw is occurring.
~~Fixed so the above code actually compiles, make sure to add -lpthread