Learning ofEvent. Help making simple video player with custom event

Hello forum!
I’ve been avoiding the use of ofEvent because I didn’t understand it and customEventExample proved to be more complex than I could understand. Because of this I decided to make a simple custom event for myself but I got nowhere so I would like to ask for help building it. It is a program that plays the “fingers.mov” on the hour every hour (just a modified videoPlayerExample).

I know I can do this without ofEvent but that is not my purpose in this activity, I don’t even want to use mouse clicks to trigger it. I’ve also read Roxlu’s presentation and reviewed an older thread I had started ( http://forum.openframeworks.cc/t/running-a-piece-of-code-once,-ofevents,-c+±question./10002/0 ) and of course, I’ve read every thread I could find about it.
Any help would be greatly appreciated of course.

One big question I do have is what is considered an event when one has a listener, just a change in the value of what is observed? can it be just a simple variable like an integer assigned to get the system hours?

h file

  
  
ofVideoPlayer   fingerMovie;  
int                 hour;  

cpp file

  
  
void testApp::setup(){  
	fingerMovie.loadMovie("fingers.mov");  
	fingerMovie.setLoopState(OF_LOOP_NONE);  
	fingerMovie.play();  
	hour = ofGetHours();  
}  
void testApp::update(){  
    fingerMovie.update();  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
    fingerMovie.draw(20,20);  
    ofDrawBitmapString("Hour: "+ofToString(hour), 20, 15);  
}  
  

As always thank you veeery much!

So I started from scratch. I’ve been studying customEventExample and now I think I had it all wrong so here are my questions:
-Does ofNotifyEvent() have to be used inside some “if” with all the logic for it?
-Does an ofEvent have to be related to a method from a certain class?
-How about relating ofEvent to a regular function?
-Does a method triggered from an event run in a parallel process to the application that notified the event? or does one have to finish for the other to start?

I’m guessing I still don’t understand the advantage of using ofEvent besides decoupling and maybe I was expecting something else.
Returning to the example I want to make I believe I’d have to do the following:
-In setup() register a listener for the app, it will listen to any event and if something happens it will point to method from a class that will run only once per event.
-Make a method that will run only once.
The following is the part that really confuses me about triggering events:
-Inside update() and for each cycle I have to take the hour value from the system time and put it in an int variable. This variable will be checked to see if it has changed and in order to do this I have to make all the "if"s requiered to do so. In case of change notify event.

I will do this now and when I’ve finished I’ll post it for anyone needing it.
Thanks :smiley:

Here is a quick example I put together that might help explain usage ( honestly ofEvent is confusing to me as well )
https://gist.github.com/4353055

Maybe that helps?

I find I use ofEvent if I need to have one class communicate to a lot of classes or the other way around.
Like if I detect that a new video has been sent to my app - I might notify a bunch of listeners that a new video has come in and then they can all do different things to get ready.

Another time it can be helpful is with a gui - where if a hit is detected on an item it can trigger an event that sends the item’s name to a lister method. The method then can perform an action for a particular event.

ie:

  
  
void eventsIn( myGuiItem & evnt ){  
  if( evnt.name == "grab background" ) cv.grabBackground();  
  if( evnt.name == "exit app") ofExit(0);   
}  
  

I hope that helps!
Check out the example I posted and see if that answers your questions.

All the best,
Theo

I got it working nicely but I do have a few questions that might help me and anyone else in the future. I may be wrong about a few things now but it does work. I will fix this in further posts if necessary.

@theo
I just posted this so I’ll read your post now and get back here afterwards.

Here is the code:

  
#pragma once  
  
#include "ofMain.h"  
  
class TimerEvent : public ofEventArgs {  
public:  
    TimerEvent() {}  
    static ofEvent <TimerEvent> events;  
};  
  
class testApp : public ofBaseApp{  
  
	public:  
  
		void setup();  
		void update();  
		void draw();  
  
		void keyPressed(int key);  
		void keyReleased(int key);  
		void mouseMoved(int x, int y );  
		void mouseDragged(int x, int y, int button);  
		void mousePressed(int x, int y, int button);  
		void mouseReleased(int x, int y, int button);  
		void windowResized(int w, int h);  
		void dragEvent(ofDragInfo dragInfo);  
		void gotMessage(ofMessage msg);  
		void                reRunMovie(TimerEvent &e);  
  
        ofVideoPlayer 	    movie;  
        int                 currentMinute;  
        int                 currentSecond;  
        int                 lastMinute;  
        int                 lastSecond;  
        int                 eventTCounter;  
  
};  
  

  
  
#include "testApp.h"  
  
ofEvent <TimerEvent> TimerEvent::events;  
  
//--------------------------------------------------------------  
void testApp::setup(){  
  
    ofBackground(0,0,0);  
    movie.loadMovie("fingers.mov");  
    movie.setLoopState(OF_LOOP_NONE);  
    movie.play();  
    currentMinute = lastMinute = 0;  
    currentSecond = lastSecond = 0;  
    eventTCounter = 0;  
  
    // listen to any timer event  
    ofAddListener(TimerEvent::events, this, &testApp::reRunMovie);  
  
}  
  
//--------------------------------------------------------------  
void testApp::reRunMovie(TimerEvent &e){  
  
    movie.setFrame(0);  
    movie.play();  
    eventTCounter++;  
  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
  
    currentMinute = ofGetMinutes();  
    currentSecond = ofGetSeconds();  
    movie.update();  
  
    if (currentMinute != lastMinute ) {  
        TimerEvent newEvent;  
        ofNotifyEvent(TimerEvent::events, newEvent);  
        lastMinute = currentMinute;  
        lastSecond = currentSecond;  
    }  
  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
  
    movie.draw(20,65);  
    ofDrawBitmapString("Current Min:Sec // "+ofToString(currentMinute,2,'0')+":"+ofToString(currentSecond,2,'0'), 20, 15);  
    ofDrawBitmapString("Last    Min:Sec // "+ofToString(lastMinute,2,'0')+":"+ofToString(lastSecond,2,'0'), 20, 30);  
    ofDrawBitmapString("Trigger Count:     "+ofToString(eventTCounter), 20, 45);  
    ofDrawBitmapString("Video length :     "+ofToString(movie.getDuration())+" minutes.", 20, 60);  
    if (movie.getIsMovieDone() == true){  
        ofDrawBitmapString("Video is not playing.", 20, 315);  
    } else {  
        ofDrawBitmapString("Video is playing.", 20, 315);  
    }  
  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed  (int key){  
}  
  
//--------------------------------------------------------------  
void testApp::keyReleased(int key){  
}  
  
//--------------------------------------------------------------  
void testApp::mouseMoved(int x, int y ){  
}  
  
//--------------------------------------------------------------  
void testApp::mouseDragged(int x, int y, int button){  
}  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
}  
  
//--------------------------------------------------------------  
void testApp::mouseReleased(int x, int y, int button){  
}  
  
//--------------------------------------------------------------  
void testApp::windowResized(int w, int h){  
}  
  
//--------------------------------------------------------------  
void testApp::gotMessage(ofMessage msg){  
}  
  
//--------------------------------------------------------------  
void testApp::dragEvent(ofDragInfo dragInfo){  
}  
  
  

everything about that looks solid to me.
its just a funny usage with the triggering :slight_smile:

@Theo
The example is useful but I was looking more for something that notifies events but is not already defined in ofEvents.h and more especifically with a time variable. I’m trying to complete the a PJLink timer that turns a projector on and off at certain times of the day without interaction (here if you are interested http://forum.openframeworks.cc/t/looking-for-advice-for-a-permanent-installation/11007/4 )
Now that I think about it I think you are right. The example gives me events with much less code. I’ll modify my example.

Is there a better way to do this? A few days ago I thought ofEvents were notified when a variable changed to any other value that the current one, that code I did was the first thing I tried when I found out they do not.
Do you have any suggestions for a better code?

Thank you very much! :smiley:

edit: I forgot one question. Do all methods of a class that would be used in events have to have arguments?
As in eventsIn(string & eventStr){…}
Since in my case it is not important to use them cant it just be eventsIn() {…} (nothing as argument).
I first tried not using them but it wouldn’t let me compile, I put them and it worked nicely.

-Edit 2->
The modification using your code as reference worked perfectly!

great!

Since in my case it is not important to use them cant it just be eventsIn() {…} (nothing as argument).
I first tried not using them but it wouldn’t let me compile, I put them and it worked nicely.

I think there might be an ofEvent argument - but you can also just use the string one and then there could always allow the possibility of some data to pass through.

Another thing you can do is pass your own object.

ie:

  
  
class customData{  
  public:  
    string timestamp;  
    int state;   
};  
  
  

Then do
ofEvent myEvent;

But you are correct in that events are not triggered by themselves - you have to decide when to send them. Its just more that it allows you to create notifications to different parts of your code.

It seems like you’ve got a pretty good idea though, now.
I hope it works out!!

All the best,
Theo

Thanks Theo for all the help and info. I will try what you’ve mentioned further on.
With your help I’ve finished the simplest timer example of ofEvent I was able to make and this time without another class as in my previous post. This example is supposed to be very easy to read and understand. The previous code had a custom event in case anyone wants to learn them.

Thanks again forum! :smiley:

I’ll leave the code here in case anyone is stuck at the beginning of ofEvents. You will need the fingers.mov video from the videoPlayerExample. This was made in of_v0073_win_cb_release .

testApp.h

  
#pragma once  
#include "ofMain.h"  
  
class testApp : public ofBaseApp{  
  
	public:  
  
		void setup();  
		void update();  
		void draw();  
  
		void keyPressed(int key);  
		void keyReleased(int key);  
		void mouseMoved(int x, int y );  
		void mouseDragged(int x, int y, int button);  
		void mousePressed(int x, int y, int button);  
		void mouseReleased(int x, int y, int button);  
		void windowResized(int w, int h);  
		void dragEvent(ofDragInfo dragInfo);  
		void gotMessage(ofMessage msg);  
  
        // "string &eventStr" argument is currently  
        //  necessary as I was unable to find ofEvent <void>  
		void                reRunMovie(string &eventStr);  
		ofEvent <string>    events;  
  
        ofVideoPlayer 	    movie;  
        int                 currentMinute;  
        int                 currentSecond;  
        int                 lastMinute;  
        int                 lastSecond;  
        int                 eventTCounter;  
  
};  
  

testApp.cpp

  
#include "testApp.h"  
  
//--------------------------------------------------------------  
void testApp::setup(){  
  
    ofBackground(0,0,0);  
    movie.loadMovie("fingers.mov");  
    movie.setLoopState(OF_LOOP_NONE);  
    movie.play();  
    currentMinute = lastMinute = 0;  
    currentSecond = lastSecond = 0;  
    eventTCounter = 0;  
  
    // listen to any timer event  
    ofAddListener(events, this, &testApp::reRunMovie);  
  
}  
  
//--------------------------------------------------------------  
void testApp::reRunMovie(string & eventStr){  
  
    movie.setFrame(0);  
    movie.play();  
    eventTCounter++;  
    // Console output of string sent from ofNotifyEvent(events, str, this);  
    cout << "Event triggered at timestamp: " << eventStr << endl;  
    // It is not necessary to do anything with the arguments  
    // but they have to be same as the type of ofEvent.  
  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
  
    currentMinute = ofGetMinutes();  
    currentSecond = ofGetSeconds();  
    movie.update();  
  
    if (currentMinute != lastMinute ) {  
        string str = ofGetTimestampString();  
        ofNotifyEvent(events, str, this);  
        lastMinute = currentMinute;  
        lastSecond = currentSecond;  
    }  
  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
  
    movie.draw(20,65);  
    ofDrawBitmapString("Current Min:Sec // "+ofToString(currentMinute,2,'0')+":"+ofToString(currentSecond,2,'0'), 20, 15);  
    ofDrawBitmapString("Last    Min:Sec // "+ofToString(lastMinute,2,'0')+":"+ofToString(lastSecond,2,'0'), 20, 30);  
    ofDrawBitmapString("Trigger Count:     "+ofToString(eventTCounter), 20, 45);  
    ofDrawBitmapString("Video length :     "+ofToString(movie.getDuration())+" minutes.", 20, 60);  
    if (movie.getIsMovieDone() == true){  
        ofDrawBitmapString("Video is not playing.", 20, 315);  
    } else {  
        ofDrawBitmapString("Video is playing.", 20, 315);  
    }  
  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed  (int key){  
}  
  
//--------------------------------------------------------------  
void testApp::keyReleased(int key){  
}  
  
//--------------------------------------------------------------  
void testApp::mouseMoved(int x, int y ){  
}  
  
//--------------------------------------------------------------  
void testApp::mouseDragged(int x, int y, int button){  
}  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
}  
  
//--------------------------------------------------------------  
void testApp::mouseReleased(int x, int y, int button){  
}  
  
//--------------------------------------------------------------  
void testApp::windowResized(int w, int h){  
}  
  
//--------------------------------------------------------------  
void testApp::gotMessage(ofMessage msg){  
}  
  
//--------------------------------------------------------------  
void testApp::dragEvent(ofDragInfo dragInfo){  
}  
  

Hi irregular and Theo,
I’ve been thinking on adding an ofEvent example that better illustrates how to implement them than the current examples (vanderlin’s ant killing example is a nice app, and implements a complex use of custom events, but is almost useless to understand how to use a basic custom event).
I’m a bit lazzy so I didn’t read thoroughly the whole thread, sorry :stuck_out_tongue:
Irregular,
although your last example indeed illustrates how to implement a custom ofEvent is kind of senseless to implement the notifier and the listener within the same class. it is the same as calling the listener’s callback method (testApp:reRunMovie(string & eventStr)) instead of the ofNotifyEvent(). ie:

  
void testApp::update(){    
    
    currentMinute = ofGetMinutes();    
    currentSecond = ofGetSeconds();    
    movie.update();    
    
    if (currentMinute != lastMinute ) {    
        string str = ofGetTimestampString();    
        reRunMovie(str);   
        lastMinute = currentMinute;    
        lastSecond = currentSecond;    
    }    
    
}    

I have some “templates” that I usualy use for custom events laying around that I can clean up and make a nice and simple custom event example.
I’ll push it to my github as soon as I have it done and let you know.

Best!

Hey Roy!
Well, as stated in the beginning, the point of the example was to use ofEvent in the simplest possible way, even if it was trivial, ofEvent was the requirement. Sure the example I proposed can be made without ofEvents but this was an exercise. I also wanted a thread with all the info I couldn’t find elsewhere.

I had no idea how ofEvent worked until after them so, to summaries the thread it is a bit like this:
1-First code was the purpose with no ofEvent and nothing working, just a video player:
http://forum.openframeworks.cc/t/learning-ofevent.-help-making-simple-video-player-with-custom-event/11574/1
2-Example posted by Theo of ofEvent within the testapp class.
https://gist.github.com/4353055
3-ofEvent with custom timer event based on customEventExample that uses a class outside testapp
http://forum.openframeworks.cc/t/learning-ofevent.-help-making-simple-video-player-with-custom-event/11574/4
4-Upgrade to the previous using the example posted by Theo
http://forum.openframeworks.cc/t/learning-ofevent.-help-making-simple-video-player-with-custom-event/11574/8

I may still be wrong about many of these things but I think they are correct. I also think it would be great to see more examples each with increasing complexity and functionality. The custoEventExample was a bit of a huge step from the other ofEvent examples.

@irregular,
sure, I understand your point.
for sure this info will be useful for more than someone.
I’ll try to make a simple example soon anyways.

slds!

Awesome! Mil gracias Roy! :smiley:

Hey @irregular and @theo

just pushed a simple event example to my github
https://github.com/roymacdonald/openFrameworks/tree/feature-simpleEventExample/examples/events/simpleEventsExample

let me know what you think

@roymacdonald
It worked great! My initial problem (I guess the common one) was the fact that for ofEvent to work it needed to be correctly coded with at least four elements in the code and even then nothing might happen on screen. Your example with all the comments is much easier to understand and it contrasts global and circle events.
It’s a much better example so thank you very much. :smiley:

Comments are good. :slight_smile:

Thanks to all here , ofEvent() it’s something that i have a bit fear to enter in, but this discussion and the examples will help me a lot!

Nice to see that it helps.
I’ve posted it at OF github and Arturo proposed to remove the global event because it’s not safe, so I’ll fix that, although I’ll implement the “global” event in a different way so functionality remains the same.

I’ll let you know when it’s ready.

cheers

@kalwalt
You are welcome! :smiley:
Funny, I could have really used this thread about a week ago.

@roymacdonald
You are feeding my curiosity! How would global events not be safe?
Can you point to the github post about it?
-Edit-> Nevermind! :stuck_out_tongue: found it! :smiley: