utils-file: improve mu_play

implement in terms of run_command
This commit is contained in:
Dirk-Jan C. Binnema
2023-09-13 23:03:51 +03:00
parent 9dcbe1d96c
commit 0a12b70d7b
2 changed files with 91 additions and 87 deletions

View File

@ -35,64 +35,6 @@
using namespace Mu;
Mu::Option<std::string>
Mu::program_in_path(const std::string& name)
{
if (char *path = g_find_program_in_path(name.c_str()); path)
return to_string_gchar(std::move(path)/*consumes*/);
else
return Nothing;
}
/*
* Set the child to a group leader to avoid being killed when the
* parent group is killed.
*/
static void
maybe_setsid (G_GNUC_UNUSED gpointer user_data)
{
#if HAVE_SETSID
setsid();
#endif /*HAVE_SETSID*/
}
Mu::Result<void>
Mu::play (const std::string& path)
{
/* check nativity */
GFile *gf = g_file_new_for_path(path.c_str());
auto is_native = g_file_is_native(gf);
g_object_unref(gf);
if (!is_native)
return Err(Error::Code::File, "'{}' is not a native file", path);
const char *prog{g_getenv ("MU_PLAY_PROGRAM")};
if (!prog) {
#ifdef __APPLE__
prog = "open";
#else
prog = "xdg-open";
#endif /*!__APPLE__*/
}
const auto program_path{program_in_path(prog)};
if (!program_path)
return Err(Error::Code::File, "cannot find '{}' in path", prog);
const gchar *argv[3]{};
argv[0] = program_path->c_str();
argv[1] = path.c_str();
argv[2] = nullptr;
GError *err{};
if (!g_spawn_async ({}, (gchar**)&argv, {}, G_SPAWN_SEARCH_PATH, maybe_setsid,
{}, {}, &err))
return Err(Error::Code::File, &err/*consumes*/,
"failed to open '{}' with '{}'", path, *program_path);
return Ok();
}
bool
Mu::check_dir (const std::string& path, bool readable, bool writeable)
{
@ -293,8 +235,22 @@ Mu::read_from_stdin()
g_memory_output_stream_get_size(G_MEMORY_OUTPUT_STREAM(outmem))});
}
/*
* Set the child to a group leader to avoid being killed when the
* parent group is killed.
*/
static void
maybe_setsid (G_GNUC_UNUSED gpointer user_data)
{
#if HAVE_SETSID
setsid();
#endif /*HAVE_SETSID*/
}
Result<Mu::CommandOutput>
Mu::run_command(std::initializer_list<std::string> args)
Mu::run_command(std::initializer_list<std::string> args, bool try_setsid)
{
std::vector<char*> argvec{};
for (auto&& arg: args)
@ -315,9 +271,8 @@ Mu::run_command(std::initializer_list<std::string> args)
static_cast<char**>(argvec.data()),
{},
(GSpawnFlags)(G_SPAWN_SEARCH_PATH),
{}, {},
&std_out, &std_err,
&wait_status, &err);
try_setsid ? maybe_setsid : nullptr, {},
&std_out, &std_err, &wait_status, &err);
for (auto& a: argvec)
g_free(a);
@ -331,6 +286,48 @@ Mu::run_command(std::initializer_list<std::string> args)
to_string_gchar(std::move(std_err/*consumed*/))});
}
Mu::Option<std::string>
Mu::program_in_path(const std::string& name)
{
if (char *path = g_find_program_in_path(name.c_str()); path)
return to_string_gchar(std::move(path)/*consumes*/);
else
return Nothing;
}
/* LCOV_EXCL_START*/
constexpr auto default_open_program =
#ifdef __APPLE__
"open"
#else
"xdg-open"
#endif /*!__APPLE__*/
;
Mu::Result<void>
Mu::play (const std::string& path)
{
/* check nativity */
GFile *gf = g_file_new_for_path(path.c_str());
auto is_native = g_file_is_native(gf);
g_object_unref(gf);
if (!is_native)
return Err(Error::Code::File, "'{}' is not a native file", path);
auto mpp{g_getenv ("MU_PLAY_PROGRAM")};
const std::string prog{mpp ? mpp : default_open_program};
const auto program_path{program_in_path(prog)};
if (!program_path)
return Err(Error::Code::File, "cannot find '{}' in path", prog);
else if (auto&& res{run_command({*program_path, path}, true/*try-setsid*/)}; !res)
return Err(std::move(res.error()));
else
return Ok();
}
/* LCOV_EXCL_STOP*/
Result<std::string>
Mu::expand_path(const std::string& str)