mirror of
https://github.com/matrix-construct/construct
synced 2024-12-25 23:14:13 +01:00
ircd: Add utility to beep the pcspeaker.
This commit is contained in:
parent
422c4da624
commit
31431d32c5
6 changed files with 232 additions and 0 deletions
|
@ -1129,6 +1129,7 @@ RB_CHK_SYSHEADER(linux/perf_event.h, [LINUX_PERF_EVENT_H])
|
|||
RB_CHK_SYSHEADER(linux/hw_breakpoint.h, [LINUX_HW_BREAKPOINT_H])
|
||||
RB_CHK_SYSHEADER(linux/io_uring.h, [LINUX_IO_URING_H])
|
||||
RB_CHK_SYSHEADER(linux/icmp.h, [LINUX_ICMP_H])
|
||||
RB_CHK_SYSHEADER(linux/input-event-codes.h, [LINUX_INPUT_EVENT_CODES_H])
|
||||
|
||||
dnl windows platform
|
||||
RB_CHK_SYSHEADER(windows.h, [WINDOWS_H])
|
||||
|
|
44
include/ircd/beep.h
Normal file
44
include/ircd/beep.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2021 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_BEEP_H
|
||||
|
||||
/// pcspkr-event-spkr
|
||||
namespace ircd
|
||||
{
|
||||
struct beep;
|
||||
}
|
||||
|
||||
/// Transmits audible tone through the pcspkr for the object's duration. The
|
||||
/// tone starts at construction and continues until terminated by destruction.
|
||||
///
|
||||
class ircd::beep
|
||||
{
|
||||
struct ctrl;
|
||||
|
||||
static ctx::mutex mutex;
|
||||
static conf::item<std::string> path;
|
||||
static conf::item<bool> debug;
|
||||
|
||||
std::unique_lock<ctx::mutex> lock;
|
||||
fs::fd fd;
|
||||
|
||||
public:
|
||||
beep(const float tone = 2600.0f);
|
||||
beep(beep &&) noexcept;
|
||||
beep(const beep &) = delete;
|
||||
beep &operator=(beep &&) noexcept;
|
||||
beep &operator=(const beep &) = delete;
|
||||
~beep() noexcept;
|
||||
|
||||
static bool available() noexcept;
|
||||
static bool busy() noexcept;
|
||||
};
|
|
@ -110,6 +110,7 @@
|
|||
#include "net/net.h"
|
||||
#include "server/server.h"
|
||||
#include "png.h"
|
||||
#include "beep.h"
|
||||
#include "magick.h"
|
||||
#include "resource/resource.h"
|
||||
#include "client.h"
|
||||
|
|
|
@ -229,6 +229,7 @@ endif
|
|||
if IMAGEMAGICK
|
||||
libircd_la_SOURCES += magick.cc
|
||||
endif
|
||||
libircd_la_SOURCES += beep.cc
|
||||
libircd_la_SOURCES += png.cc
|
||||
if OPENCL
|
||||
libircd_la_SOURCES += cl.cc
|
||||
|
|
158
ircd/beep.cc
Normal file
158
ircd/beep.cc
Normal file
|
@ -0,0 +1,158 @@
|
|||
// The Construct
|
||||
//
|
||||
// Copyright (C) The Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2021 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#if __has_include(<linux/input-event-codes.h>)
|
||||
#include <linux/input-event-codes.h>
|
||||
#endif
|
||||
|
||||
#ifndef EV_SND
|
||||
#define EV_SND 0
|
||||
#endif
|
||||
|
||||
#ifndef SND_TONE
|
||||
#define SND_TONE 0
|
||||
#endif
|
||||
|
||||
/// Event device file structure.
|
||||
struct ircd::beep::ctrl
|
||||
{
|
||||
struct timeval tv {0};
|
||||
uint16_t type {EV_SND};
|
||||
uint16_t code {SND_TONE};
|
||||
int32_t tone {0};
|
||||
};
|
||||
|
||||
decltype(ircd::beep::mutex)
|
||||
ircd::beep::mutex;
|
||||
|
||||
decltype(ircd::beep::path)
|
||||
ircd::beep::path
|
||||
{
|
||||
{ "name", "ircd.beep.path" },
|
||||
{ "default", "/dev/input/by-path/platform-pcspkr-event-spkr" },
|
||||
};
|
||||
|
||||
decltype(ircd::beep::debug)
|
||||
ircd::beep::debug
|
||||
{
|
||||
{ "name", "ircd.beep.debug" },
|
||||
{ "default", false },
|
||||
};
|
||||
|
||||
/// Is another ircd::ctx currently beeping?
|
||||
bool
|
||||
ircd::beep::busy()
|
||||
noexcept
|
||||
{
|
||||
return mutex.locked();
|
||||
}
|
||||
|
||||
/// Is beeping at all possible for this platform?
|
||||
bool
|
||||
ircd::beep::available()
|
||||
noexcept try
|
||||
{
|
||||
return path && fs::exists(path);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::derror
|
||||
{
|
||||
"Failed to detect PC Speaker event availability :%s",
|
||||
e.what()
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// beep::beep
|
||||
//
|
||||
|
||||
ircd::beep::beep(const float tone)
|
||||
try
|
||||
:lock
|
||||
{
|
||||
tone > 0.0f?
|
||||
std::unique_lock<ctx::mutex>{mutex}:
|
||||
std::unique_lock<ctx::mutex>{mutex, std::defer_lock}
|
||||
}
|
||||
,fd
|
||||
{
|
||||
tone > 0.0f?
|
||||
fs::fd{string_view{path}, std::ios::out}:
|
||||
fs::fd{-1}
|
||||
}
|
||||
{
|
||||
if(!fd)
|
||||
return;
|
||||
|
||||
beep::ctrl c;
|
||||
c.tone = tone;
|
||||
syscall(::write, int(fd), &c, sizeof(c));
|
||||
|
||||
if(debug)
|
||||
log::debug
|
||||
{
|
||||
"PC Speaker audible tone active @ %-1.1f Hz",
|
||||
tone,
|
||||
};
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
"Failed to activate audible alarm :%s",
|
||||
e.what(),
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
ircd::beep::beep(beep &&other)
|
||||
noexcept
|
||||
:lock{std::move(other.lock)}
|
||||
,fd{std::move(other.fd)}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::beep &
|
||||
ircd::beep::operator=(beep &&other)
|
||||
noexcept
|
||||
{
|
||||
this->~beep();
|
||||
lock = std::move(other.lock);
|
||||
fd = std::move(other.fd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ircd::beep::~beep()
|
||||
noexcept try
|
||||
{
|
||||
if(!fd)
|
||||
return;
|
||||
|
||||
assert(mutex.locked());
|
||||
assert(this->lock.owns_lock());
|
||||
|
||||
beep::ctrl c;
|
||||
c.tone = 0;
|
||||
syscall(::write, int(fd), &c, sizeof(c));
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::derror
|
||||
{
|
||||
"Failed to clear pcspkr event (%p)",
|
||||
this,
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
|
@ -619,6 +619,33 @@ console_cmd__sync(opt &out, const string_view &line)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__beep(opt &out, const string_view &line)
|
||||
{
|
||||
const params param{line, " ",
|
||||
{
|
||||
"frequency", "duration"
|
||||
}};
|
||||
|
||||
const auto tone
|
||||
{
|
||||
param.at("frequency", 2600.0f)
|
||||
};
|
||||
|
||||
const auto duration
|
||||
{
|
||||
param.at("duration", 250ms)
|
||||
};
|
||||
|
||||
beep beep
|
||||
{
|
||||
tone
|
||||
};
|
||||
|
||||
ctx::sleep(duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// log
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue