3 * Copyright (C) 2013-2023 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_LOG_THREAD_HPP_INCLUDED
19 #define CARLA_LOG_THREAD_HPP_INCLUDED
21 #include "CarlaBackend.h"
22 #include "CarlaString.hpp"
23 #include "CarlaThread.hpp"
34 using CARLA_BACKEND_NAMESPACE::EngineCallbackFunc
;
36 // -----------------------------------------------------------------------
39 class CarlaLogThread
: private CarlaThread
43 : CarlaThread("CarlaLogThread"),
47 fCallbackPtr(nullptr) {}
60 // TODO: use process id instead
61 const int randint
= std::rand();
65 std::snprintf(strBuf
, 0xff, "\\\\.\\pipe\\carlalogthread-%i", randint
);
67 fPipe
[0] = CreateNamedPipeA(strBuf
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
|PIPE_READMODE_BYTE
|PIPE_NOWAIT
, 2, 4096, 4096, 0, nullptr);
68 fPipe
[1] = CreateFileA(strBuf
, GENERIC_WRITE
, 0x0, nullptr, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, nullptr);
70 CARLA_SAFE_ASSERT_RETURN(fPipe
[0] != INVALID_HANDLE_VALUE
,);
71 CARLA_SAFE_ASSERT_RETURN(fPipe
[1] != INVALID_HANDLE_VALUE
,);
73 const int pipe1
= _open_osfhandle((INT_PTR
)fPipe
[1], _O_WRONLY
| _O_BINARY
);
74 const int stdout_fileno
= _fileno(stdout
);
75 const int stderr_fileno
= _fileno(stderr
);
77 CARLA_SAFE_ASSERT_RETURN(pipe(fPipe
) == 0,);
79 if (fcntl(fPipe
[0], F_SETFL
, O_NONBLOCK
) != 0)
86 const int pipe1
= fPipe
[1];
87 const int stdout_fileno
= STDOUT_FILENO
;
88 const int stderr_fileno
= STDERR_FILENO
;
91 fStdOut
= dup(stdout_fileno
);
92 fStdErr
= dup(stderr_fileno
);
94 dup2(pipe1
, stdout_fileno
);
95 dup2(pipe1
, stderr_fileno
);
111 CloseHandle(fPipe
[0]);
112 CloseHandle(fPipe
[1]);
114 const int stdout_fileno
= _fileno(stdout
);
115 const int stderr_fileno
= _fileno(stderr
);
120 const int stdout_fileno
= STDOUT_FILENO
;
121 const int stderr_fileno
= STDERR_FILENO
;
124 dup2(fStdOut
, stdout_fileno
);
125 dup2(fStdErr
, stderr_fileno
);
132 void setCallback(EngineCallbackFunc callback
, void* callbackPtr
)
134 CARLA_SAFE_ASSERT_RETURN(callback
!= nullptr,);
136 fCallback
= callback
;
137 fCallbackPtr
= callbackPtr
;
143 CARLA_SAFE_ASSERT_RETURN(fCallback
!= nullptr,);
145 size_t k
, bufTempPos
;
147 char bufTemp
[1024+1];
148 char bufRead
[1024+1];
149 char bufSend
[2048+1];
154 while (! shouldThreadExit())
158 while ((r
= read(fPipe
[0], bufRead
, 1024)) > 0)
160 CARLA_SAFE_ASSERT_CONTINUE(r
<= 1024);
165 for (ssize_t i
=0; i
<r
; ++i
)
167 CARLA_SAFE_ASSERT_BREAK(bufRead
[i
] != '\0');
169 if (bufRead
[i
] != '\n')
172 k
= static_cast<size_t>(i
-lastRead
);
176 std::memcpy(bufSend
, bufTemp
, bufTempPos
);
177 std::memcpy(bufSend
+bufTempPos
, bufRead
+lastRead
, k
);
182 std::memcpy(bufSend
, bufRead
+lastRead
, k
);
190 fCallback(fCallbackPtr
, CARLA_BACKEND_NAMESPACE::ENGINE_CALLBACK_DEBUG
, 0, 0, 0, 0, 0.0f
, bufSend
);
193 if (lastRead
> 0 && lastRead
!= r
)
195 k
= static_cast<size_t>(r
-lastRead
);
196 std::memcpy(bufTemp
, bufRead
+lastRead
, k
);
216 EngineCallbackFunc fCallback
;
220 ssize_t
read(const HANDLE pipeh
, void* const buf
, DWORD numBytes
)
222 if (ReadFile(pipeh
, buf
, numBytes
, &numBytes
, nullptr) != FALSE
)
228 //CARLA_PREVENT_HEAP_ALLOCATION
229 CARLA_DECLARE_NON_COPYABLE(CarlaLogThread
)
238 // -----------------------------------------------------------------------
240 #endif // CARLA_LOG_THREAD_HPP_INCLUDED