Stop and restart CoreAudio daemon under '_coreaudiod' user and not under root - c++

I am developing an app which needs to have exclusive access to the USB sound device. I found out that when the music is playing using this device then sometimes it is not possible to get access. So I need to stop and restart CoreAudio daemon.
I am using this piece of code (below) to get it work. But the problem is that after coreaudiod is stopped I can run it only under root user. By default it is ran under _coreaudiod user. How can I run it under _coreaudiod user as it's done by the OS?
#include <CoreFoundation/CFDictionary.h>
#include <Security/Authorization.h>
class ScopedAudioServiceStopper
{
public:
ScopedAudioServiceStopper();
~ScopedAudioServiceStopper();
void stop();
private:
void start();
private:
AuthorizationRef m_authorizationRef;
CFDictionaryRef m_coreAudiodDictionary;
};
ScopedAudioServiceStopper::~ScopedAudioServiceStopper()
{
start();
if (m_coreAudiodDictionary)
CFRelease(m_coreAudiodDictionary);
if (m_authorizationRef)
AuthorizationFree(m_authorizationRef, kAuthorizationFlagDestroyRights);
}
void ScopedAudioServiceStopper::stop()
{
m_coreAudiodDictionary = SMJobCopyDictionary(kSMDomainSystemLaunchd, CFSTR("com.apple.audio.coreaudiod"));
if (!m_coreAudiodDictionary) //means daemon is not started
return;
if (errAuthorizationSuccess != AuthorizationCreate(nullptr, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &m_authorizationRef)) {
m_authorizationRef = nullptr;
return;
}
AuthorizationItem authItem = { kSMRightModifySystemDaemons, 0, nullptr, 0 };
AuthorizationRights authRights = { 1, &authItem };
AuthorizationFlags flags = kAuthorizationFlagDefaults |
kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagPreAuthorize |
kAuthorizationFlagExtendRights;
// Obtain the right to install our privileged helper tool (kSMRightModifySystemDaemons).
if (errAuthorizationSuccess != AuthorizationCopyRights(m_authorizationRef, &authRights, kAuthorizationEmptyEnvironment, flags, nullptr)) {
m_authorizationRef = nullptr;
return;
}
CFErrorRef cfError;
if (!SMJobRemove(kSMDomainSystemLaunchd, CFSTR("com.apple.audio.coreaudiod"), m_authorizationRef, TRUE, &cfError)) {
CFRelease(cfError);
}
}
void ScopedAudioServiceStopper::start()
{
if (!m_authorizationRef || !m_coreAudiodDictionary)
return;
CFErrorRef cfError;
if (!SMJobSubmit(kSMDomainSystemLaunchd, m_coreAudiodDictionary, m_authorizationRef, &cfError)) {
CFRelease(cfError);
}
}

Related

Boost Message queue Not receiving across two processes

I wrote a small test app to use the Boos Message_Queue to send data between two processes. That all worked correctly and I was able to print the data that I sent.
I moved my test code into my main project and now the main project is not waking from the Receives. The main project runs as systems so I tracked down one error and saw that the message_queue was not checking the same memory location for some reason. I defined BOOST_INTERPROCESS_SHARED_DIR_PATH and then the main project was able to open the queue created by the test app. But when the test app sends the main project never woke from its receive. The main project should be running as system and the test app as a user. But I figured since it is sharing the memory location it should work correctly?
If I open the queue in the test app again it wakes and receives all of the messages right away. Am I missing something or is this a limitation on BOOST message_queue?
The code from the test app:
MessageQueue::MessageQueue(int, boost::interprocess::permissions perm) :
mq(boost::interprocess::create_only, "TestChannel", 100, sizeof(QueueData), perm)
{
}
MessageQueue::MessageQueue(bool) :
mq(boost::interprocess::open_only, "TestChannel")
{
}
MessageQueue::~MessageQueue()
{
int num = mq.get_num_msg();
wprintf(_T("sent: %d\n"), num);
boost::interprocess::message_queue::remove("TestChannel");
}
void MessageQueue::SetCommand(int i)
{
QueueData qd;
qd.fakeInfo = i;
qd.exit = false;
CoCreateGuid(&qd.msgGuid);
mq.send(&qd, sizeof(qd), 0);
OLECHAR* uidOleStr;
if (StringFromCLSID(qd.msgGuid, &uidOleStr) != S_OK)
throw std::runtime_error("Unknown error occurred when trying to convert a GUID to string!");
// Copy the ole str into a CString and then free it immediately, so we don't have to worry about it.
CString guidString(uidOleStr);
CoTaskMemFree(uidOleStr);
wprintf(_T("sent: %d, %s\n"), qd.fakeInfo, guidString);
}
void MessageQueue::WaitForCommand()
{
while(true)
{
QueueData qd;
size_t size, pri;
mq.receive(&qd, sizeof(qd), size, pri);
if (qd.fakeInfo == 2)
sendExit();
OLECHAR* uidOleStr;
if (StringFromCLSID(qd.msgGuid, &uidOleStr) != S_OK)
throw std::runtime_error("Unknown error occurred when trying to convert a GUID to string!");
// Copy the ole str into a CString and then free it immediately, so we don't have to worry about it.
CString guidString(uidOleStr);
CoTaskMemFree(uidOleStr);
wprintf(_T("Recieved: %d, %s\n"), qd.fakeInfo, guidString);
if (qd.exit)
break;
}
}
void MessageQueue::sendExit()
{
QueueData qd;
qd.exit = true;
mq.send(&qd, sizeof(qd), 0);
wprintf(_T("Sent Exit"));
}
.h file:
#pragma once
#define BOOST_INTERPROCESS_SHARED_DIR_PATH "C:\\Program Files (x86)\\Users"
#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/interprocess/permissions.hpp>
class QueueData
{
public:
int fakeInfo;
GUID msgGuid;
bool exit;
};
class MessageQueue
{
public:
MessageQueue(int, boost::interprocess::permissions perm);
MessageQueue(bool);
~MessageQueue();
boost::interprocess::message_queue mq;
void SetCommand(int);
void WaitForCommand();
void sendExit();
};
test app running code: (I have been using breakpoints)
void waiter()
{
MessageQueue mq(true);
mq.WaitForCommand();
}
void sender()
{
boost::interprocess::permissions perm;
perm.set_unrestricted();
try
{
boost::interprocess::message_queue::remove("TestChannel");
MessageQueue mq(2, perm);
mq.SetCommand(1);
mq.SetCommand(1);
mq.SetCommand(2);
}
catch (boost::interprocess::interprocess_exception e)
{
}
}
int main() {
waiter();
sender();
}
The code from the main project: (To test I did have it use the wait of the above code and still nothing)
void MemoryChannel::WaitForCmd( const std::function< void ( MemoryChannelCmd cmd, const char *pData, TCHAR *tempPath, GUID msgGuid ) > func )
{
QueueData mcObject;
size_t size, pri;
while (true)
{
pMCD->dataQueue.timed_receive(&mcObject, sizeof(mcObject), size, pri, boost::posix_time::microsec_clock::universal_time() + boost::posix_time::milliseconds(30000));
size_t num = pMCD->dataQueue.get_num_msg();
//func(MemoryChannelCmd::MEMORY_CHANNEL_RUN_SQL_SELECT, "", _T(""), mcObject.msgGuid);
}
}
Doesn't seem to be a code issue since it works in the test app but not in the main project even sharing code.
I am at a loss.
For inter-process communication the higher privilege process must start first. Only then can lower privilege processes can connect.
In your example system process should start the queue, test app connects and then they can communicate. This is why it works when restarting the test app.
It's designed this way to prevent lower privilege users to access higher privilege user memory without permission.

Gtk/C++ Chronometer

I'm doing a game that uses a chronometer.
The game is written in C++ and I'm also using glade and GTK3.0
My problem is that when I start the game the chronometer doesn't work as it should..
I have created a file time.h with this code inside:
struct aTimer
{
bool running = false;
int hour_expired = 0;
int min_expired = 59;
int sec_expired = 50;
};
void start_time(aTimer *&t)
{
t->running = true;
}
void reset_time(aTimer *&t)
{
t->running = false;
t->sec_expired = 0;
t->min_expired = 0;
t->hour_expired = 0;
}
In my main file, I include it and also declare a new chronometer like this:
void start_time(aTimer *&);
void reset_time(aTimer *&);
aTimer *tempo = new aTimer;
Now, in my game, I have 2 windows, when i press play from the first window, the second window becomes visible and I hide the first one. When the second one is closed, the first becomes visible and the second invisible..
When the first window is closed, the application is closed.
In the struct, the bool running is false, because my idea was to make it true when you actually play the game (that is when you have the second window visible) and not at the start of the application..
So I've done this in the main file:
void start_game()
{
start_time(tempo);
}
gboolean update_time()
{
if (tempo->running)
{
if (tempo->sec_expired == 60)
{
tempo->sec_expired = 0;
(tempo->min_expired)++;
if (tempo->min_expired == 60)
{
tempo->min_expired = 0;
(tempo->hour_expired)++;
}
}
ostringstream oss;
GtkLabel *time = GTK_LABEL(gtk_builder_get_object(builder, "lblSec"));
oss<<(tempo->sec_expired)++;
gtk_label_set_text(time, oss.str().c_str());
oss.str("");
oss.clear();
time = GTK_LABEL(gtk_builder_get_object(builder, "lblMin"));
oss<<tempo->min_expired<<":";
gtk_label_set_text(time, oss.str().c_str());
oss.str("");
oss.clear();
time = GTK_LABEL(gtk_builder_get_object(builder, "lblHour"));
oss<<tempo->hour_expired<<":";
gtk_label_set_text(time, oss.str().c_str());
oss.str("");
oss.clear();
}
return tempo->running;
}
and in the main function of the main file i have also:
g_timeout_add_seconds(1, GSourceFunc(update_time), NULL);
If I start the application with the bool running = false, it won't work at all
If I start it the running = true, then it does work when i start the application, but as i come back to the "menu" and want to play another game, it won't start again.. The new time will just be the old time and won't increment anymore
I don't understand why though... Can someone help me?
Thank you
********************UPDATE************************
I tried the GTimer "option" as #José Fonte suggested but still can't come ahead..
This is an example that i tried..
#include <iostream>
#include <glib.h>
#include <sstream>
#include <gtk/gtk.h>
static GtkBuilder *builder;
using namespace std;
GTimer *timing;
bool start = false;
extern "C" void btnStartPause_click(GtkButton *button)
{
if (!start)
{
timing = g_timer_new();
start = true;
}
else
{
g_timer_stop(timing);
start = false;
}
}
gboolean update_time()
{
if (start)
{
gulong *micro;
double sec;
sec = g_timer_elapsed(timing, micro);
ostringstream oss;
GtkLabel *time = GTK_LABEL(gtk_builder_get_object(builder, "lblSec"));
oss<<(sec)++;
gtk_label_set_text(time, oss.str().c_str());
oss.str("");
oss.clear();
}
return start;
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder,"glade.glade", NULL);
gtk_builder_connect_signals(builder, NULL);
// timing
g_timeout_add_seconds(1, GSourceFunc(update_time), NULL);
gtk_main();
return 0;
}
The problem again is.. I wanna start the timing when i click the btnStartPause button (not when i start the application), so i want it to start in the btnClick function..
But it seems like that the application tries instantly to do the gboolean update_time() function but since at the start of the application the boolean start is false, it just won't do the code, but when i click the button, so that the boolean start becomes true, it doesn't try again the gboolean update_time(), like it tried at the start of the application, and won't try it anymore.. I don't understand this..

Thread does not do anything

I try to use a thread to tell the user the COM port for serial communication he entered was wrong. I have a thread class which tries to establish the connection and a function in my main, that should tell the user.
The compiler does not complain, but my program never enters the function. Maybe anyone can spot the mistake I made.
main.cpp:
WindowsDgpsGUIFrame::WindowsDgpsGUIFrame(wxWindow* parent,wxWindowID id)
{
...
Bind(wxEVT_THREAD, &WindowsDgpsGUIFrame::onConnectionFailed, this, wxID_EXIT);
...
}
void WindowsDgpsGUIFrame::OnButtonStartClick(wxCommandEvent& event)
{
NavigationThread* navigationThread = new NavigationThread(this, m_usedVariables);
m_navigationThread = navigationThread;
wxThreadError err = m_navigationThread->Create();
if(err != wxTHREAD_NO_ERROR)
{
StaticStatusText->Enable();
StaticStatusText->SetLabel("Could not create NavigationThread.");
}
else{
StaticStatusText->SetLabel("Thread created");
}
err = m_navigationThread->Run();
if(err != wxTHREAD_NO_ERROR)
{
StaticStatusText->SetLabel("Could not run thread.");
}
}
void WindowsDgpsGUIFrame::onConnectionFailed(wxThreadEvent& event)
{
StaticConnectionText->SetLabel(event.GetString());
}
thread.cpp:
wxThread::ExitCode NavigationThread::Entry()
{
Serial serial;
int resultGnss = serial.Open(m_gnssPort, STANDARD_BAUDRATE);
wxThreadEvent event(wxEVT_THREAD, wxID_RETRY);
if(resultGnss != 0)
{
event.SetString("Connection to GNSS box not possible. Try with another COM port.");
m_parent->GetEventHandler()->AddPendingEvent(event);
}
else{
event.SetString("Connection successful");
m_parent->GetEventHandler()->AddPendingEvent(event);
}
return 0;
}
The thread gets created and starts running, but even though the event is thrown in the thread the program never reaches onConnectionFailed().

C++ / Qt - Passing self to pthread_create

I am working on a Qt GUI that will handle a single client. I am NOT using the Qt TCP libraries or the Qt thread library. I am creating my own Server class (more or less for the experience/learning).
I wanted to make sure what I am doing with the pthread handler isn't going to come back to haunt me in the future. My question is... Is it bad practice to pass this into the pthread_create function? Could this cause problems? It seems to work ok but I am always weary about problems lurking when working with threads.
I will be happy to share more code if it is needed. Thanks for taking a look.
Server.hpp
class Server : public Socket{
public:
....
TCPSocket *accept() throw(SocketException);
static void *listen_for_clients(void *);
void start() throw(SocketException);
void set_listen() throw(SocketException);
private:
pthread_t listen_thread;
};
Server.cpp
void HandleTCPClient(TCPSocket *sock);
TCPSocket *Server::accept() throw(SocketException)
{
int new_conn_sd;
if ( (new_conn_sd = ::accept(socket_descriptor, NULL, 0)) < 0)
{
throw SocketException("Server: accept failed", true);
}
return new TCPSocket(new_conn_sd);
}
void *Server::listen_for_clients(void *ptr)
{
Server * p = (Server *)ptr;
p->set_listen();
for (;;)
{
HandleTCPClient(p->accept());
}
return 0;
}
void Server::start() throw(SocketException)
{
if(pthread_create(&listen_thread, NULL, listen_for_clients, this)) {
throw SocketException("Server: cannot create listen thread", true);
}
}
void Server::set_listen() throw(SocketException)
{
if (listen(socket_descriptor, queue_length) < 0)
{
throw SocketException("Server: set listening socket failed", true);
}
}
void HandleTCPClient(TCPSocket *sock) {
std::cout << "Handling client ";
.....
delete sock;
}

avr-gcc: No such file or directory

I have been following the TinyOS tutorial at this link: http://www.cse.wustl.edu/~lu/cse521s/Slides/tutorial.pdf. I cannot get the final project code to compile in tinyos. I'm using windows xp with cygwin and all the latest rpms. When I try to compile the code with "make micaz" I get and error stating "avr gcc: no file or directory found". Here is the code. thanks in advance.
Makefile:
COMPONENT=DemoAppC
include $(MAKERULES)
DemoMessage.h
#ifndef __DEMOMESSAGE_H
#define __DEMOMESSAGE_H
enum
{
AM_DEMO_MSG = 231,
};
typedef nx_struct demo_msg
{
nx_uint16_t lastReading;
} demo_msg_t;
#endif
DemoP.nc
module DemoP
{
uses interface Boot;
uses interface Leds;
uses interface Read<uint16_t>;
uses interface SplitControl as RadioControl;
uses interface AMSend;
uses interface Receive;
uses interface Packet;
uses interface Timer<TMilli>;
}
implementation
{
message_t buf;
task void readSensor();
task void sendBuffer();
event void Boot.booted()
{
if(call RadioControl.start() != SUCCESS)
call Leds.led0On();
}
event void RadioControl.startDone(error_t err)
{
if(err != SUCCESS)
call Leds.led0On();
if(TOS_NODE_ID == 0)
call Timer.startPeriodic(64);
}
event void Timer.fired()
{
post readSensor();
}
task void readSensor()
{
if(call Read.read() != SUCCESS)
post readSensor();
}
event void Read.readDone(error_t err, uint16_t val)
{
demo_msg_t * payload = (demo_msg_t *)call Packet.getPayload(&buf, sizeof(d
payload->lastReading = val;
post sendBuffer();
}
task void sendBuffer()
{
if(call AMSend.send(AM_BROADCAST_ADDR,
&buf, sizeof(demo_msg_t)) != SUCCESS)
post sendBuffer();
}
event void AMSend.sendDone(message_t * jkdsakljads, error_t err)
{
if(err != SUCCESS)
post sendBuffer();
}
event message_t * Receive.receive(message_t * m,void * payload,uint8_t size)
{
demo_msg_t * dpayload = (demo_msg_t *)payload;
call Leds.set(dpayload->lastReading / 200);
return m;
}
event void RadioControl.stopDone(error_t err) {}
DemoAppC.nc
#include "DemoMessage.h"
configuration DemoAppC{}
implementation{
components DemoP, MainC;
DemoP.Boot -> MainC.Boot;
components LedsC;
DemoP.Leds -> LedsC;
components new HamamatsuS10871TsrC() as PhotoSensor;
DemoP.Read -> PhotoSensor;
components ActiveMessageC;
DemoP.RadioControl -> ActiveMessageC;
components new AMSenderC(AM_DEMO_MSG),
new AMReceiverC(AM_DEMO_MSG);
DemoP.AMSend -> AMSenderC;
DemoP.Receive -> AMReceiverC;
DemoP.Packet -> AMSenderC;
components new TimerMilliC();
DemoP.Timer -> TimerMilliC;
}
I had the same issue. Had to install avr-gcc from https://github.com/osx-cross/homebrew-avr
avr-gcc must not be installed correctly. Make sure you have all of the RPMs from http://docs.tinyos.net/tinywiki/index.php/Manual_installation_using_RPM_packages under the avr section installed.
If rpm -ivh avr-gcc-4.1.2-1.cygwin.i386.rpm returns that the package is already installed then you need to add/usr/bin to your $PATH.