Browse Source

+ added libjack example program simple_client.pp (translated from simple_client.c)

Nikolay Nikolov 7 months ago
parent
commit
863fe13bd1
2 changed files with 175 additions and 0 deletions
  1. 172 0
      packages/libjack/examples/simple_client.pp
  2. 3 0
      packages/libjack/fpmake.pp

+ 172 - 0
packages/libjack/examples/simple_client.pp

@@ -0,0 +1,172 @@
+{
+  This simple client demonstrates the most basic features of JACK
+  as they would be used by many applications.
+}
+
+program simple_client;
+
+{$MODE objfpc}{$H+}
+
+uses
+  Jack, CTypes, SysUtils;
+
+var
+  input_port: Pjack_port_t;
+  output_port: Pjack_port_t;
+  client: Pjack_client_t;
+
+{
+  The process callback for this JACK application is called in a
+  special realtime thread once for each audio cycle.
+
+  This client does nothing more than copy data from its input
+  port to its output port. It will exit when stopped by
+  the user (e.g. using Ctrl-C on a unix-ish operating system)
+}
+function process (nframes: jack_nframes_t; arg: Pointer): cint; cdecl;
+var
+  _in: Pjack_default_audio_sample_t;
+  _out: Pjack_default_audio_sample_t;
+begin
+  _in := jack_port_get_buffer (input_port, nframes);
+  _out := jack_port_get_buffer (output_port, nframes);
+  Move(_in^, _out^,
+       SizeOf(jack_default_audio_sample_t) * nframes);
+
+  Result := 0;
+end;
+
+{
+  JACK calls this shutdown_callback if the server ever shuts down or
+  decides to disconnect the client.
+}
+procedure jack_shutdown (arg: Pointer); cdecl;
+begin
+  Halt (1);
+end;
+
+var
+  ports: PPChar;
+  client_name: PChar = 'simple';
+  server_name: PChar = nil;
+  options: jack_options_t = JackNullOption;
+  status: jack_status_t;
+begin
+  { open a client connection to the JACK server }
+
+  client := jack_client_open (client_name, options, @status, server_name);
+  if client = nil then
+  begin
+    Writeln(StdErr, 'jack_client_open() failed, ',
+            'status = $', HexStr(Ord(status), 4));
+    if (Ord(status) and Ord(JackServerFailed)) <> 0  then
+    begin
+      Writeln(StdErr, 'Unable to connect to JACK server');
+    end;
+    Halt (1);
+  end;
+  if (Ord(status) and Ord(JackServerStarted)) <> 0 then
+  begin
+    Writeln (StdErr, 'JACK server started');
+  end;
+  if (Ord(status) and Ord(JackNameNotUnique)) <> 0 then
+  begin
+    client_name := jack_get_client_name(client);
+    Writeln (StdErr, 'unique name `', client_name, ''' assigned');
+  end;
+
+  { tell the JACK server to call `process()' whenever
+    there is work to be done.
+  }
+
+  jack_set_process_callback (client, @process, nil);
+
+  { tell the JACK server to call `jack_shutdown()' if
+    it ever shuts down, either entirely, or if it
+    just decides to stop calling us.
+  }
+
+  jack_on_shutdown (client, @jack_shutdown, nil);
+
+  { display the current sample rate.
+  }
+
+  Writeln ('engine sample rate: ',
+           jack_get_sample_rate (client));
+
+  { create two ports }
+
+  input_port := jack_port_register (client, 'input',
+                                    JACK_DEFAULT_AUDIO_TYPE,
+                                    Ord(JackPortIsInput), 0);
+  output_port := jack_port_register (client, 'output',
+                                     JACK_DEFAULT_AUDIO_TYPE,
+                                     Ord(JackPortIsOutput), 0);
+
+  if (input_port = nil) or (output_port = nil) then
+  begin
+    Writeln(StdErr, 'no more JACK ports available');
+    Halt (1);
+  end;
+
+  { Tell the JACK server that we are ready to roll.  Our
+    process() callback will start running now. }
+
+  if jack_activate (client) <> 0 then
+  begin
+    Writeln (StdErr, 'cannot activate client');
+    Halt (1);
+  end;
+
+  { Connect the ports.  You can't do this before the client is
+    activated, because we can't make connections to clients
+    that aren't running.  Note the confusing (but necessary)
+    orientation of the driver backend ports: playback ports are
+    "input" to the backend, and capture ports are "output" from
+    it.
+  }
+
+  ports := jack_get_ports (client, nil, nil,
+                           Ord(JackPortIsPhysical) or Ord(JackPortIsOutput));
+  if ports = nil then
+  begin
+    Writeln(StdErr, 'no physical capture ports');
+    Halt (1);
+  end;
+
+  if jack_connect (client, ports[0], jack_port_name (input_port)) <> 0 then
+  begin
+    Writeln (StdErr, 'cannot connect input ports');
+  end;
+
+  jack_free (ports);
+
+  ports := jack_get_ports (client, nil, nil,
+                           Ord(JackPortIsPhysical) or Ord(JackPortIsInput));
+  if ports = nil then
+  begin
+    Writeln(StdErr, 'no physical playback ports');
+    Halt (1);
+  end;
+
+  if jack_connect (client, jack_port_name (output_port), ports[0]) <> 0 then
+  begin
+    Writeln (StdErr, 'cannot connect output ports');
+  end;
+
+  jack_free (ports);
+
+  { keep running until stopped by the user }
+
+  repeat
+    sleep (High(Cardinal));
+  until False;
+
+  { this is never reached but if the program
+    had some other way to exit besides being killed,
+    they would be important to call.
+  }
+
+  jack_client_close (client);
+  Halt (0);
+end.

+ 3 - 0
packages/libjack/fpmake.pp

@@ -37,6 +37,9 @@ begin
         AddInclude('weakmacros.inc');
       end;
 
+    P.ExamplePath.Add('examples');
+    P.Targets.AddExampleProgram('simple_client.pp');
+
     P.NamespaceMap:='namespaces.lst';
 
 {$ifndef ALLPACKAGES}