Beispiel #1
0
void loop() {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);

    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    physics_start();

    while (!glfwWindowShouldClose(window) && running) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        if (pthread_mutex_trylock(&lock) == 0) {
            for (int i = 0; i < PARTICLES_MAX; i++) {
                struct particle *p = &array[i];
                if (!p->m) continue;
                
                glPointSize(particle_radius(p) * 2.0f);

                double x, y;
                double alpha = particle_getcoords(*p, &x, &y);

                glColor4d(p->color[0], p->color[1], p->color[2], alpha);
                
                glBegin(GL_POINTS);
                glVertex2d(x, y);
                glEnd();
            }
            pthread_mutex_unlock(&lock);
        }

        if (mouse.is_dragging) {
            double x, y;
            glfwGetCursorPos(window, &x, &y);

            glBegin(GL_LINES);
            glColor3dv(next_color);

            glVertex2d(mouse.xp, mouse.yp);
            glVertex2d(x, y);

            glEnd();
        }

        glfwSwapBuffers(window);
        glfwPollEvents();

        glfwSetWindowTitle(window, newtitle());
    }

    physics_stop();
}
//static
gboolean LLMediaImplGStreamer::bus_callback(GstBus *bus, GstMessage *message, gpointer data)
{
#ifdef LL_GST_REPORT_STATE_CHANGES
	LL_DEBUGS("MediaCallback") << "Got GST message type: " << GST_MESSAGE_TYPE_NAME (message) << LL_ENDL;
#endif

	LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data;

	switch (GST_MESSAGE_TYPE (message)) 
	{
		case GST_MESSAGE_BUFFERING: 
		{
			gint percent = 0;
			gst_message_parse_buffering(message, &percent);
#ifdef LL_GST_REPORT_STATE_CHANGES
			LL_DEBUGS("MediaBuffering") << "GST buffering: " << percent << "%%" << LL_ENDL;
#endif
			LLMediaEvent event( impl, percent );
			impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
		}
			break;
		case GST_MESSAGE_STATE_CHANGED: 
		{
			GstState old_state;
			GstState new_state;
			GstState pending_state;
			gst_message_parse_state_changed(message,
						&old_state,
						&new_state,
						&pending_state);
#ifdef LL_GST_REPORT_STATE_CHANGES
		// not generally very useful, and rather spammy.
		LL_DEBUGS("MediaState") << "GST state change (old,<new>,pending): "<< get_gst_state_name(old_state) << ",<" << get_gst_state_name(new_state) << ">," << get_gst_state_name(pending_state) << LL_ENDL;
#endif // LL_GST_REPORT_STATE_CHANGES

			switch (new_state) 
			{
			case GST_STATE_VOID_PENDING:
				break;
			case GST_STATE_NULL:
#ifdef LL_GST_REPORT_STATE_CHANGES
				LL_DEBUGS("MediaImpl") << "State changed to NULL" << LL_ENDL;
#endif
				if (impl->getState() == GST_STATE_PLAYING) 
				{ 
					// Stream was probably dropped, trying to restart
				    impl->play();
#ifdef LL_GST_REPORT_STATE_CHANGES
				    LL_DEBUGS("MediaImpl") << "Trying to restart." << LL_ENDL;
#endif
				}
				break;
			case GST_STATE_READY:
				break;
			case GST_STATE_PAUSED:
				break;
			case GST_STATE_PLAYING:
				//impl->mLastTitle = "";

				LLMediaEvent event( impl, 100 );
				impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
				// emit an event to say that a media source was loaded
				LLMediaEvent event2( impl );
				impl->getEventEmitter().update( &LLMediaObserver::onMediaLoaded, event2 );
				break;
			}
			break;
		}
		case GST_MESSAGE_ERROR: 
		{
			GError *err = NULL;
			gchar *debug = NULL;

			gst_message_parse_error (message, &err, &debug);
			LL_WARNS("MediaImpl") << "GST Error: " << err->message << LL_ENDL;
			g_error_free (err);
			g_free (debug);

			impl->addCommand(LLMediaBase::COMMAND_STOP);
			//impl->addCommand(LLMediaBase::COMMAND_START);

			break;
		}
		case GST_MESSAGE_INFO: 
		{
			GError *err = NULL;
			gchar *debug = NULL;
			
			gst_message_parse_info (message, &err, &debug);
			LL_INFOS("MediaImpl") << "GST info: " << err->message
														<< LL_ENDL;
			g_error_free (err);
			g_free (debug);
			break;
		}
		case GST_MESSAGE_WARNING: 
		{
			GError *err = NULL;
			gchar *debug = NULL;

			gst_message_parse_warning (message, &err, &debug);
			LL_WARNS("MediaImpl") << "GST warning: " <<  err->message
		    << LL_ENDL;
			g_error_free (err);
			g_free (debug);

			break;
		}
		case GST_MESSAGE_TAG: 
		{
			GstTagList *new_tags;

			gst_message_parse_tag( message, &new_tags );

			gchar *title;

			if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) )
			{
				LL_INFOS("MediaInfo") << "Title: " << title << LL_ENDL;
				std::string newtitle(title);
				gst_tag_list_free(new_tags);

				if ( newtitle != impl->mLastTitle && newtitle != "" )
				{
					impl->mLastTitle = newtitle;
					LLMediaEvent event( impl, impl->mLastTitle );
					impl->getEventEmitter().update( &LLMediaObserver::onMediaTitleChange, event );
				}

				g_free(title);
			}

			break;
		}
		case GST_MESSAGE_EOS:
		{
			/* end-of-stream */
			LL_DEBUGS("MediaImpl") << "GST end-of-stream." << LL_ENDL;
			if (impl->isLooping())
			{
				LL_DEBUGS("MediaImpl") << "looping media..." << LL_ENDL;
				impl->stop();
				impl->play();
			}
			else
			{
				// inject a COMMAND_STOP
				impl->addCommand(LLMediaBase::COMMAND_STOP);
			}
			break;
		}
		default:
			/* unhandled message */
			break;
	}
	/* we want to be notified again the next time there is a message
	 * on the bus, so return true (false means we want to stop watching
	 * for messages on the bus and our callback should not be called again)
	 */
	return TRUE;
}
gboolean
MediaPluginGStreamer010::processGSTEvents(GstBus     *bus,
					  GstMessage *message)
{
	if (!message) 
		return TRUE; // shield against GStreamer bug

	if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED &&
	    GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
	{
		DEBUGMSG("Got GST message type: %s",
			GST_MESSAGE_TYPE_NAME (message));
	}
	else
	{
		// TODO: grok 'duration' message type
		DEBUGMSG("Got GST message type: %s",
			 GST_MESSAGE_TYPE_NAME (message));
	}

	switch (GST_MESSAGE_TYPE (message))
	{
		case GST_MESSAGE_BUFFERING:
		{
			// NEEDS GST 0.10.11+ and America discovered by C.Columbus
			gint percent = 0;
			gst_message_parse_buffering(message, &percent);
			DEBUGMSG("GST buffering: %d%%", percent);

			break;
		}
		case GST_MESSAGE_STATE_CHANGED: {
			GstState old_state;
			GstState new_state;
			GstState pending_state;
			gst_message_parse_state_changed(message,
							&old_state,
							&new_state,
							&pending_state);
			#ifdef LL_GST_REPORT_STATE_CHANGES
			// not generally very useful, and rather spammy.
			DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s",
				get_gst_state_name(old_state),
				get_gst_state_name(new_state),
				get_gst_state_name(pending_state));
			#endif // LL_GST_REPORT_STATE_CHANGES

			switch (new_state) 
			{
				case GST_STATE_VOID_PENDING:
					break;
				case GST_STATE_NULL:
					break;
				case GST_STATE_READY:
					setStatus(STATUS_LOADED);
					break;
				case GST_STATE_PAUSED:
					setStatus(STATUS_PAUSED);
					break;
				case GST_STATE_PLAYING:
					setStatus(STATUS_PLAYING);
					break;
			}
			break;
		}
		case GST_MESSAGE_ERROR:
		{
			GError *err = NULL;
			gchar *debug = NULL;
	
			gst_message_parse_error (message, &err, &debug);
			WARNMSG("GST error: %s", err?err->message:"(unknown)");
			if (err)
				g_error_free (err);
			g_free (debug);
	
			mCommand = COMMAND_STOP;
	
			setStatus(STATUS_ERROR);
	
			break;
		}
		case GST_MESSAGE_INFO:
		{
			GError *err = NULL;
			gchar *debug = NULL;
			
			gst_message_parse_info (message, &err, &debug);
			INFOMSG("GST info: %s", err?err->message:"(unknown)");
			if (err)
				g_error_free (err);
			g_free (debug);

			break;
		}
		case GST_MESSAGE_WARNING:
		{
			GError *err = NULL;
			gchar *debug = NULL;
	
			gst_message_parse_warning (message, &err, &debug);
			WARNMSG("GST warning: %s", err?err->message:"(unknown)");
			if (err)
				g_error_free (err);
			g_free (debug);
	
			break;
		}
		case GST_MESSAGE_TAG: 
		{
			GstTagList *new_tags;

			gst_message_parse_tag( message, &new_tags );

			gchar *title = NULL;

			if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) )
			{
				//WARMING("Title: %s", title);
				std::string newtitle(title);
				gst_tag_list_free(new_tags);

				if ( newtitle != mLastTitle && !newtitle.empty() )
				{
					LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
					message.setValue("name", newtitle );
					sendMessage( message );
					mLastTitle = newtitle;
				}
				g_free(title);
			}

			break;
		}
		case GST_MESSAGE_EOS:
		{
			/* end-of-stream */
			DEBUGMSG("GST end-of-stream.");
			if (mIsLooping)
			{
				DEBUGMSG("looping media...");
				double eos_pos_sec = 0.0F;
				bool got_eos_position = getTimePos(eos_pos_sec);
	
				if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
				{
					// if we know that the movie is really short, don't
					// loop it else it can easily become a time-hog
					// because of GStreamer spin-up overhead
					DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec);
					// inject a COMMAND_PAUSE
					mCommand = COMMAND_PAUSE;
				}
				else
				{
					#undef LLGST_LOOP_BY_SEEKING
					// loop with a stop-start instead of a seek, because it actually seems rather
					// faster than seeking on remote streams.
					#ifdef LLGST_LOOP_BY_SEEKING
					// first, try looping by an explicit rewind
					bool seeksuccess = seek(0.0);
					if (seeksuccess)
					{
						play(1.0);
					}
					else
					#endif // LLGST_LOOP_BY_SEEKING
					{  // use clumsy stop-start to loop
						DEBUGMSG("didn't loop by rewinding - stopping and starting instead...");
						stop();
						play(1.0);
					}
				}
			}
			else // not a looping media
			{
				// inject a COMMAND_STOP
				mCommand = COMMAND_STOP;
			}
		} break;

		default:
			/* unhandled message */
			break;
	}

	/* we want to be notified again the next time there is a message
	 * on the bus, so return true (false means we want to stop watching
	 * for messages on the bus and our callback should not be called again)
	 */
	return TRUE;
}