adopt to winsock
[melted] / src / examples / server.cpp
1 #include <iostream>
2 #include <string>
3 #include <cstring>
4 #include <sstream>
5 using namespace std;
6
7 #include <Mlt.h>
8 #include <MltMelted.h>
9 #include <MltResponse.h>
10 using namespace Mlt;
11
12 class Custom : public Melted
13 {
14 private:
15 Event *event;
16 Profile profile;
17
18 public:
19 Custom( char *name = "Custom", int port = 5290, char *config = NULL ) :
20 Melted( name, port, config ),
21 event( NULL )
22 {
23 // Ensure that we receive the MLT XML document before it's deserialised
24 set( "push-parser-off", 1 );
25 }
26
27 virtual ~Custom( )
28 {
29 delete event;
30 }
31
32 // Optional step - receive the MLT XML document and do something with it
33 Response *received( char *command, char *document )
34 {
35 cerr << document << endl;
36 Producer producer( profile, "xml-string", document );
37 return push( command, &producer );
38 }
39
40 // Push handling - clear the playlist, append, seek to beginning and play
41 Response *push( char*, Service *service )
42 {
43 Playlist playlist( ( mlt_playlist )( unit( 0 )->get_data( "playlist" ) ) );
44 Producer producer( *service );
45 if ( producer.is_valid( ) && playlist.is_valid( ) )
46 {
47 playlist.lock( );
48 playlist.clear( );
49 playlist.append( producer );
50 playlist.seek( 0 );
51 playlist.set_speed( 1 );
52 playlist.unlock( );
53 return new Response( 200, "OK" );
54 }
55 return new Response( 400, "Invalid" );
56 }
57
58 // Custom command execution
59 Response *execute( char *command )
60 {
61 Response *response = NULL;
62
63 if ( !strcmp( command, "debug" ) )
64 {
65 // Example of a custom command
66 response = new Response( 200, "Diagnostics output" );
67 for( int i = 0; unit( i ) != NULL; i ++ )
68 {
69 Properties *properties = unit( i );
70 stringstream output;
71 output << string( "Unit " ) << i << endl;
72 for ( int j = 0; j < properties->count( ); j ++ )
73 output << properties->get_name( j ) << " = " << properties->get( j ) << endl;
74 response->write( output.str( ).c_str( ) );
75 }
76 }
77 else
78 {
79 // Use the default command processing
80 response = Melted::execute( command );
81 }
82
83 // If no event exists and the first unit has been added...
84 if ( event == NULL && unit( 0 ) != NULL )
85 {
86 // Set up the event handling
87 Consumer consumer( ( mlt_consumer )( unit( 0 )->get_data( "consumer" ) ) );
88 event = consumer.listen( "consumer-frame-render", this, ( mlt_listener )frame_render );
89
90 // In this custom case, we'll loop everything on the unit
91 Playlist playlist( ( mlt_playlist )( unit( 0 )->get_data( "playlist" ) ) );
92 playlist.set( "eof", "loop" );
93 }
94
95 return response;
96 }
97
98 // Callback for frame render notification
99 static void frame_render( mlt_consumer, Custom *self, mlt_frame frame_ptr )
100 {
101 Frame frame( frame_ptr );
102 self->frame_render_event( frame );
103 }
104
105 // Remove all supers and attributes
106 void frame_render_event( Frame &frame )
107 {
108 // Fetch the c double ended queue structure
109 mlt_deque deque = ( mlt_deque )frame.get_data( "data_queue" );
110
111 // While the deque isn't empty
112 while( deque != NULL && mlt_deque_peek_back( deque ) != NULL )
113 {
114 // Fetch the c properties structure
115 mlt_properties cprops = ( mlt_properties )mlt_deque_pop_back( deque );
116
117 // For fun, convert it to c++ and output it :-)
118 Properties properties( cprops );
119 properties.debug( );
120
121 // Wipe it
122 mlt_properties_close( cprops );
123 }
124 }
125 };
126
127 int main( int, char** )
128 {
129 Custom server( "Server" );
130 server.start( );
131 server.execute( "uadd sdl" );
132 server.execute( "play u0" );
133 server.wait_for_shutdown( );
134 return 0;
135 }
136