simple_session_client.pp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. {
  2. This simple client demonstrates the most basic features of JACK
  3. as they would be used by many applications.
  4. this version also adds session manager functionality.
  5. }
  6. program simple_session_client;
  7. {$MODE objfpc}{$H+}
  8. uses
  9. Jack, JackSession, CTypes, SysUtils;
  10. var
  11. input_port: Pjack_port_t;
  12. output_port: Pjack_port_t;
  13. client: Pjack_client_t;
  14. simple_quit: Boolean = False;
  15. {
  16. The process callback for this JACK application is called in a
  17. special realtime thread once for each audio cycle.
  18. This client does nothing more than copy data from its input
  19. port to its output port. It will exit when stopped by
  20. the user (e.g. using Ctrl-C on a unix-ish operating system)
  21. }
  22. function process (nframes: jack_nframes_t; arg: Pointer): cint; cdecl;
  23. var
  24. _in: Pjack_default_audio_sample_t;
  25. _out: Pjack_default_audio_sample_t;
  26. begin
  27. _in := jack_port_get_buffer (input_port, nframes);
  28. _out := jack_port_get_buffer (output_port, nframes);
  29. Move(_in^, _out^,
  30. SizeOf(jack_default_audio_sample_t) * nframes);
  31. Result := 0;
  32. end;
  33. procedure session_callback (event: Pjack_session_event_t; arg: Pointer); cdecl;
  34. var
  35. retval: string;
  36. begin
  37. Writeln ('session notification');
  38. Write ('path ', event^.session_dir, ', uuid ', event^.client_uuid, ', type: ');
  39. if event^._type = JackSessionSave then
  40. Writeln ('save')
  41. else
  42. Writeln ('quit');
  43. WriteStr(retval, 'jack_simple_session_client ', event^.client_uuid);
  44. event^.command_line := StrNew (PChar(retval));
  45. jack_session_reply( client, event );
  46. if event^._type = JackSessionSaveAndQuit then
  47. simple_quit := True;
  48. jack_session_event_free (event);
  49. end;
  50. {
  51. JACK calls this shutdown_callback if the server ever shuts down or
  52. decides to disconnect the client.
  53. }
  54. procedure jack_shutdown (arg: Pointer); cdecl;
  55. begin
  56. Halt (1);
  57. end;
  58. var
  59. ports: PPChar;
  60. client_name: PChar = 'simple';
  61. server_name: string = '';
  62. options: jack_options_t = JackNullOption;
  63. status: jack_status_t;
  64. begin
  65. { open a client connection to the JACK server }
  66. if ParamCount = 1 then
  67. begin
  68. server_name := ParamStr(1);
  69. options := JackSessionId;
  70. end;
  71. client := jack_client_open (client_name, options, @status, PChar(server_name));
  72. if client = nil then
  73. begin
  74. Writeln(StdErr, 'jack_client_open() failed, ',
  75. 'status = $', HexStr(Ord(status), 4));
  76. if (Ord(status) and Ord(JackServerFailed)) <> 0 then
  77. begin
  78. Writeln(StdErr, 'Unable to connect to JACK server');
  79. end;
  80. Halt (1);
  81. end;
  82. if (Ord(status) and Ord(JackServerStarted)) <> 0 then
  83. begin
  84. Writeln (StdErr, 'JACK server started');
  85. end;
  86. if (Ord(status) and Ord(JackNameNotUnique)) <> 0 then
  87. begin
  88. client_name := jack_get_client_name(client);
  89. Writeln (StdErr, 'unique name `', client_name, ''' assigned');
  90. end;
  91. { tell the JACK server to call `process()' whenever
  92. there is work to be done.
  93. }
  94. jack_set_process_callback (client, @process, nil);
  95. { tell the JACK server to call `jack_shutdown()' if
  96. it ever shuts down, either entirely, or if it
  97. just decides to stop calling us.
  98. }
  99. jack_on_shutdown (client, @jack_shutdown, nil);
  100. { tell the JACK server to call `session_callback()' if
  101. the session is saved.
  102. }
  103. jack_set_session_callback (client, @session_callback, nil);
  104. { display the current sample rate.
  105. }
  106. Writeln ('engine sample rate: ',
  107. jack_get_sample_rate (client));
  108. { create two ports }
  109. input_port := jack_port_register (client, 'input',
  110. JACK_DEFAULT_AUDIO_TYPE,
  111. Ord(JackPortIsInput), 0);
  112. output_port := jack_port_register (client, 'output',
  113. JACK_DEFAULT_AUDIO_TYPE,
  114. Ord(JackPortIsOutput), 0);
  115. if (input_port = nil) or (output_port = nil) then
  116. begin
  117. Writeln(StdErr, 'no more JACK ports available');
  118. Halt (1);
  119. end;
  120. { Tell the JACK server that we are ready to roll. Our
  121. process() callback will start running now. }
  122. if jack_activate (client) <> 0 then
  123. begin
  124. Writeln (StdErr, 'cannot activate client');
  125. Halt (1);
  126. end;
  127. { Connect the ports. You can't do this before the client is
  128. activated, because we can't make connections to clients
  129. that aren't running. Note the confusing (but necessary)
  130. orientation of the driver backend ports: playback ports are
  131. "input" to the backend, and capture ports are "output" from
  132. it.
  133. }
  134. { only do the autoconnect when not reloading from a session.
  135. in case of a session reload, the SM will restore our connections
  136. }
  137. if ParamCount = 0 then
  138. begin
  139. ports := jack_get_ports (client, nil, nil,
  140. Ord(JackPortIsPhysical) or Ord(JackPortIsOutput));
  141. if ports = nil then
  142. begin
  143. Writeln(StdErr, 'no physical capture ports');
  144. Halt (1);
  145. end;
  146. if jack_connect (client, ports[0], jack_port_name (input_port)) <> 0 then
  147. begin
  148. Writeln (StdErr, 'cannot connect input ports');
  149. end;
  150. jack_free (ports);
  151. ports := jack_get_ports (client, nil, nil,
  152. Ord(JackPortIsPhysical) or Ord(JackPortIsInput));
  153. if ports = nil then
  154. begin
  155. Writeln(StdErr, 'no physical playback ports');
  156. Halt (1);
  157. end;
  158. if jack_connect (client, jack_port_name (output_port), ports[0]) <> 0 then
  159. begin
  160. Writeln (StdErr, 'cannot connect output ports');
  161. end;
  162. jack_free (ports);
  163. end;
  164. { keep running until until we get a quit event }
  165. while not simple_quit do
  166. sleep (1000);
  167. { this is never reached but if the program
  168. had some other way to exit besides being killed,
  169. they would be important to call.
  170. }
  171. jack_client_close (client);
  172. Halt (0);
  173. end.