/* Libvisual - The audio visualisation framework. * * Copyright (C) 2004, 2005, 2006 Dennis Smit * * Authors: Dennis Smit * * $Id: lv_event.c,v 1.27 2006/01/23 21:06:24 synap Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include "lvconfig.h" #include "lv_event.h" #include "lv_log.h" static int eventqueue_dtor (VisObject *object); static int event_list_destroy (void *data); static int eventqueue_dtor (VisObject *object) { VisEventQueue *eventqueue = VISUAL_EVENTQUEUE (object); visual_collection_destroy (VISUAL_COLLECTION (&eventqueue->events)); return VISUAL_OK; } static int event_list_destroy (void *data) { VisEvent *event = VISUAL_EVENT (data); if (event == NULL) return 0; visual_object_unref (VISUAL_OBJECT (event)); return 0; } /** * @defgroup VisEvent VisEvent * @{ */ /** * Creates a new VisEvent structure. * * @see visual_actor_get_eventqueue * * @return A newly allocated VisEvent */ VisEvent *visual_event_new () { VisEvent *event; event = visual_mem_new0 (VisEvent, 1); visual_event_init (event); /* Do the VisObject initialization*/ visual_object_set_allocated (VISUAL_OBJECT (event), TRUE); visual_object_ref (VISUAL_OBJECT (event)); return event; } int visual_event_init (VisEvent *event) { visual_log_return_val_if_fail (event != NULL, -VISUAL_ERROR_EVENT_NULL); /* Do the VisObject initialization */ visual_object_clear (VISUAL_OBJECT (event)); visual_object_set_dtor (VISUAL_OBJECT (event), NULL); visual_object_set_allocated (VISUAL_OBJECT (event), FALSE); /* Set the VisEvent data */ visual_object_clean (VISUAL_OBJECT (event), VisEvent); return VISUAL_OK; } int visual_event_copy (VisEvent *dest, VisEvent *src) { visual_log_return_val_if_fail (dest != NULL, -VISUAL_ERROR_EVENT_NULL); visual_log_return_val_if_fail (src != NULL, -VISUAL_ERROR_EVENT_NULL); /* FIXME: This is far from safe, since it won't do any refcounting jobs */ visual_object_copy_data (dest, src, VisEvent); return VISUAL_OK; } /** * Creates a new VisEventQueue data structure. * * @return Newly allocated VisEventQueue. */ VisEventQueue *visual_event_queue_new () { VisEventQueue *eventqueue; eventqueue = visual_mem_new0 (VisEventQueue, 1); visual_event_queue_init (eventqueue); /* Do the VisObject initialization*/ visual_object_set_allocated (VISUAL_OBJECT (eventqueue), TRUE); visual_object_ref (VISUAL_OBJECT (eventqueue)); return eventqueue; } int visual_event_queue_init (VisEventQueue *eventqueue) { visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); /* Do the VisObject initialization */ visual_object_clear (VISUAL_OBJECT (eventqueue)); visual_object_set_dtor (VISUAL_OBJECT (eventqueue), eventqueue_dtor); visual_object_set_allocated (VISUAL_OBJECT (eventqueue), FALSE); /* Set the VisEventQueue data */ visual_object_clean (VISUAL_OBJECT (eventqueue), VisEventQueue); eventqueue->mousestate = VISUAL_MOUSE_UP; visual_collection_set_destroyer (VISUAL_COLLECTION (&eventqueue->events), event_list_destroy); visual_event_init (&eventqueue->lastresize); return VISUAL_OK; } /** * Polls for new events. Looks at the event queue for new events and deletes * them from the queue while loading them into the event argument. * * @param eventqueue Pointer to a VisEventQueue from which new events should be taken. * @param event Pointer to a VisEvent in which the new events should be loaded. * * @return TRUE when events are handled and FALSE when the queue is out of events. */ int visual_event_queue_poll (VisEventQueue *eventqueue, VisEvent *event) { VisEvent *lev; int more_events; more_events = visual_event_queue_poll_by_reference (eventqueue, &lev); if (more_events != FALSE) { visual_event_copy (event, lev); /* FIXME when we start to ref count attributes in events, we need to unref here */ visual_object_unref (VISUAL_OBJECT (lev)); } return more_events; } int visual_event_queue_poll_by_reference (VisEventQueue *eventqueue, VisEvent **event) { VisEvent *lev; VisListEntry *listentry = NULL;; visual_log_return_val_if_fail (eventqueue != NULL, FALSE); visual_log_return_val_if_fail (event != NULL, FALSE); /* FIXME solve this better */ if (eventqueue->resizenew == TRUE) { eventqueue->resizenew = FALSE; *event = visual_event_new (); visual_event_copy (*event, &eventqueue->lastresize); return TRUE; } if (eventqueue->eventcount <= 0) return FALSE; lev = visual_list_next (&eventqueue->events, &listentry); *event = lev; visual_list_delete (&eventqueue->events, &listentry); eventqueue->eventcount--; return TRUE; } /** * Adds an event to the event queue. Add new VisEvents into the VisEventQueue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param event Pointer to a VisEvent that needs to be added to the queue. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL or -VISUAL_ERROR_EVENT_NULL * on failure. */ int visual_event_queue_add (VisEventQueue *eventqueue, VisEvent *event) { visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); visual_log_return_val_if_fail (event != NULL, -VISUAL_ERROR_EVENT_NULL); /* We've got way too much on the queue, not adding events, the important * event.resize event got data in the event queue structure that makes sure it gets * looked at */ if (eventqueue->eventcount > VISUAL_EVENT_MAXEVENTS) { visual_object_unref (VISUAL_OBJECT (event)); return -1; } visual_list_add (&eventqueue->events, event); eventqueue->eventcount++; return VISUAL_OK; } /** * Adds a new keyboard event to the event queue. By giving keyboard state information * a new VisEvent will be created and added to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param keysym A keysym from the VisKey enumerate to set the key to which the event relates. * @param keymod Key modifier information from the VisKeyMod enumerate. * @param state Contains information about whatever the key is down or up. * * return VISUAL_OK on succes -VISUAL_ERROR_EVENT_QUEUE_NULL, -VISUAL_ERROR_EVENT_NULL or error values * returned by visual_event_queue_add on failure. */ int visual_event_queue_add_keyboard (VisEventQueue *eventqueue, VisKey keysym, int keymod, VisKeyState state) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); event = visual_event_new (); if (event == NULL) { visual_log (VISUAL_LOG_CRITICAL, _("Cannot create a new VisEvent structure")); return -VISUAL_ERROR_EVENT_NULL; } /* FIXME name to VISUAL_KEYB_DOWN and KEYB_UP */ if (state == VISUAL_KEY_DOWN) event->type = VISUAL_EVENT_KEYDOWN; else event->type = VISUAL_EVENT_KEYUP; event->event.keyboard.keysym.sym = keysym; event->event.keyboard.keysym.mod = keymod; return visual_event_queue_add (eventqueue, event); } /** * Adds a new mouse movement event to the event queue. By giving absolute X and Y coordinates * for the mouse a new VisEvent will be created and added to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param x Absolute X value for the mouse location. * @param y Absolute Y value for the mouse location. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL or error values returned by * visual_event_queue_add () on failure. */ int visual_event_queue_add_mousemotion (VisEventQueue *eventqueue, int x, int y) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); event = visual_event_new (); event->type = VISUAL_EVENT_MOUSEMOTION; event->event.mousemotion.state = eventqueue->mousestate; event->event.mousemotion.x = x; event->event.mousemotion.y = y; event->event.mousemotion.xrel = x - eventqueue->mousex; event->event.mousemotion.yrel = y - eventqueue->mousey; eventqueue->mousex = x; eventqueue->mousey = y; return visual_event_queue_add (eventqueue, event);; } /** * Adds a new mouse button event to the event queue. By giving a mouse button index number and * a mouse button key state a new VisEvent will be created and added to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param button Index that indicates to which mouse button the state relates. * @param state Contains information about whatever the button is down or up * @param x Absolute X value for the mouse location. * @param y Absolute Y value for the mouse location. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL or error values returned by * visual_event_queue_add () on failure. */ int visual_event_queue_add_mousebutton (VisEventQueue *eventqueue, int button, VisMouseState state, int x, int y) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); event = visual_event_new (); if (state == VISUAL_MOUSE_DOWN) event->type = VISUAL_EVENT_MOUSEBUTTONDOWN; else event->type = VISUAL_EVENT_MOUSEBUTTONUP; event->event.mousebutton.button = button; event->event.mousebutton.state = state; event->event.mousebutton.x = x; event->event.mousebutton.y = y; eventqueue->mousestate = state; return visual_event_queue_add (eventqueue, event); } /** * Adds a new dimension change event to the event queue. By giving a pointer to * the VisVideo containing all the surface information and new width and height * a new VisEvent will be created and added to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param video Pointer to the VisVideo containing all the display information, * also used for negotiation so values can change within the VisVideo * structure. * @param width The width for the new surface. * @param height The height for the new surface. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL on failure. */ int visual_event_queue_add_resize (VisEventQueue *eventqueue, VisVideo *video, int width, int height) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); event = &eventqueue->lastresize; event->type = VISUAL_EVENT_RESIZE; /* FIXME ref counting */ event->event.resize.video = video; event->event.resize.width = width; event->event.resize.height = height; eventqueue->resizenew = TRUE; return VISUAL_OK; } /** * Adds a new song change event to the event queue. By giving a pointer to the * new VisSongInfo structure a new VisEvent will be created and added to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param songinfo Pointer to the VisSongInfo containing all the new song information. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL, -VISUAL_ERROR_SONGINFO_NULL * or error values returned by visual_event_queue_add () on failure. */ int visual_event_queue_add_newsong (VisEventQueue *eventqueue, VisSongInfo *songinfo) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); visual_log_return_val_if_fail (songinfo != NULL, -VISUAL_ERROR_SONGINFO_NULL); event = visual_event_new (); event->type = VISUAL_EVENT_NEWSONG; /* FIXME refcounting */ event->event.newsong.songinfo = songinfo; return visual_event_queue_add (eventqueue, event); } /** * Adds a new parameter change event to the event queue. By giving the pointer to the * VisParamEntry structure a new VisEvent will be created and added to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param param Pointer to the VisParamEntry containing the parameter that has been changed. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL, -VISUAL_ERROR_PARAM_NULL * or error values returned by visual_event_queue_add () on failure. */ int visual_event_queue_add_param (VisEventQueue *eventqueue, void *param) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); visual_log_return_val_if_fail (param != NULL, -VISUAL_ERROR_PARAM_NULL); event = visual_event_new (); event->type = VISUAL_EVENT_PARAM; /* FIXME ref count the param */ event->event.param.param = param; return visual_event_queue_add (eventqueue, event); } /** * Adds a new quit event to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param pass_zero_please Might be used in the future, but for now just pass. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL * or error values returned by visual_event_queue_add () on failure. */ int visual_event_queue_add_quit (VisEventQueue *eventqueue, int pass_zero_please) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); event = visual_event_new (); event->type = VISUAL_EVENT_QUIT; return visual_event_queue_add (eventqueue, event); } /** * Adds a new visibility event to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param is_visible TRUE when visible, FALSE when not visible. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL * or error values returned by visual_event_queue_add () on failure. */ int visual_event_queue_add_visibility (VisEventQueue *eventqueue, int is_visible) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); event = visual_event_new (); event->type = VISUAL_EVENT_VISIBILITY; event->event.visibility.is_visible = is_visible; return visual_event_queue_add (eventqueue, event); } /** * Adds a new generic event to the event queue. * * @param eventqueue Pointer to the VisEventQueue to which new events are added. * @param eid ID of the custom event.. * @param param_int Integer value for the custom event. * @param param_ptr Pointer to data for the custom event.. * * @return VISUAL_OK on succes, -VISUAL_ERROR_EVENT_QUEUE_NULL * or error values returned by visual_event_queue_add () on failure. */ int visual_event_queue_add_generic (VisEventQueue *eventqueue, int eid, int param_int, void *param_ptr) { VisEvent *event; visual_log_return_val_if_fail (eventqueue != NULL, -VISUAL_ERROR_EVENT_QUEUE_NULL); event = visual_event_new (); event->type = VISUAL_EVENT_GENERIC; event->event.generic.event_id = eid; event->event.generic.data_int = param_int; event->event.generic.data_ptr = param_ptr; return visual_event_queue_add (eventqueue, event); } /** * @} */