After realizing it is nearly impossible to find help on getting keybindings to work with the C plugin in MPV (Possible to allow key bindings with MPV C API when no video (GUI) is being shown?), I decided to learn some Lua to help with the cause. Problem is, the docs aren't very clear on how to add Lua scripts with the C plugin, what I could find out was that check_error(mpv_set_option_string(ctx, "load-scripts", "yes")); should be called before initializing mpv in the C plugin, which points out that there should be a way to add scripts... When loading a script in the terminal you can do mpv video.mp4 --scripts="script_name.lua" and that will call the script from inside $HOME/.config/mpv... How do I achieve the calling of Lua scripts in the C plugin for MPV? I tried a few things including check_error(mpv_set_option_string(ctx, "scripts", "test.lua")); and check_error(mpv_set_property_string(ctx, "scripts", "test.lua")); and const char *cmd2[] = {"scripts", "test.lua", NULL}; check_error(mpv_command(ctx, cmd2));, none of which worked...
How do I call a Lua script for MPV from the C Plugin?
Below is the code I'm using to test things out:
// Build with: g++ main.cpp -o output `pkg-config --libs --cflags mpv`
#include <iostream>
#include <mpv/client.h>
static inline void check_error(int status)
{
if (status < 0)
{
std::cout << "mpv API error: " << mpv_error_string(status) << std::endl;
exit(1);
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout << "pass a single media file as argument" << std::endl;
return 1;
}
mpv_handle *ctx = mpv_create();
if (!ctx)
{
std::cout << "failed creating context" << std::endl;
return 1;
}
// Enable default key bindings, so the user can actually interact with
// the player (and e.g. close the window).
check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes"));
mpv_set_option_string(ctx, "input-vo-keyboard", "yes");
check_error(mpv_set_option_string(ctx, "load-scripts", "yes"));
check_error(mpv_set_option_string(ctx, "scripts", "test.lua")); // DOES NOT WORK :(
int val = 1;
check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val));
// Done setting up options.
check_error(mpv_initialize(ctx));
// Play the file passed in as a parameter when executing program.
const char *cmd[] = {"loadfile", argv[1], NULL};
check_error(mpv_command(ctx, cmd));
// check_error(mpv_set_option_string(ctx, "scripts", "test.lua"));
check_error(mpv_set_option_string(ctx, "shuffle", "yes")); // shuffle videos
check_error(mpv_set_option_string(ctx, "loop-playlist", "yes")); // loop playlists
// check_error(mpv_set_option_string(ctx, "aspect", "0:0")); // set aspect
// Let it play, and wait until the user quits.
while (1)
{
mpv_event *event = mpv_wait_event(ctx, 10000);
std::cout << "event: " << mpv_event_name(event->event_id) << std::endl;
if (event->event_id == MPV_EVENT_SHUTDOWN)
break;
}
mpv_terminate_destroy(ctx);
return 0;
}
After playing around more with the mpv_set_property_string command, I discovered that you have to specify the FULL path to the Lua file, it by defaults searches for the file in the directory it is being played in, so if I tried to play it in /home/ it will search for /home/test.lua, so to get it to work I had to do check_error(mpv_set_property_string(ctx, "scripts", "/home/netsu/.config/mpv/test.lua")); (give the absolute path)
Related
I am trying to change the desktop background/wallpaper to a different image with a .png file. Although when I run the program, the background turns to solid black instead.
I am certain that I typed the file name, "ksa.png", correctly in my code to be the image I want to be on my background. I used an if condition to write out the last error on a file when the error occurred and used an else condition to write out "Success" if no errors occurred; but when I run the program, it writes "Success" to the file. I have thought about using a .jpg file instead, thinking that maybe .png files just don't work. I'll give an update when I tried using that.
#include <windows.h>
#include <fstream>
int main () {
const wchar_t *filenm = L"ksa.png";
std::ofstream log;
if (SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)filenm, SPIF_UPDATEINIFILE) == FALSE) {
log.open("log.txt");
log << "Error: " << GetLastError();
log.close();
}
else {
log.open("log.txt");
log << "Success";
log.close();
}
return 0;
}
When I run this program, the desktop background is suppose to be set as the image "ksa.png". Instead it's solid black. Any help is appreciated for making this work, thank you.
UPDATE
Okay so I updated the code to where it would run a .jpg file and I'm still getting the same result. Also I moved the line log.open("log.txt") command before the SystemParametersInfo() function like Remy Lebeau suggested and it still writes out "Success" to the file. I'm still having the same problem.
Here is my updated code:
#include <windows.h>
#include <fstream>
int main () {
const wchar_t *filenm = L"3.jpg";
std::ofstream log;
log.open("log.txt");
if (SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)filenm, SPIF_UPDATEINIFILE) == FALSE) {
log << "Error: " << GetLastError();
log.close();
}
else {
log.open("log.txt");
log << "Success";
log.close();
}
return 0;
}
Emmmm,there is a problem with your picture path. I've tried your code. You can't get pictures under relative paths unless you use absolute paths.
Like Cody Gray♦'s judgment .
const wchar_t *filenm = L"C:\\Users\\strives\\Desktop\\timg.bmp";
After my first successful attempt at a 3D engine using Java and OpenGL (LWJGL3), I have decided to try my hand at Vulkan, using C++.
I have barely any experience with C/C++ and I am aware of the steep learning curve of Vulkan. This is however not a problem.
I decided to follow this tutorial: https://vulkan-tutorial.com/Introduction
It has showed me how to create a new project with Vulkan using XCode (as I am on Mac OS Mojave). I would, however, like to continue the rest of the tutorial using CLion as I would be switching between multiple operating systems.
I tried my hand at creating a CLion project and succeeded in making my first CMakeLists file, however something seems to be wrong. The file currently consists of the following:
cmake_minimum_required(VERSION 3.12)
project(VulkanTesting)
set(CMAKE_CXX_STANDARD 14)
add_executable(VulkanTesting main.cpp)
include_directories(/usr/local/include)
include_directories(/Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/include)
target_link_libraries(VulkanTesting /usr/local/lib/libglfw.3.3.dylib)
target_link_libraries(VulkanTesting /Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/lib/libvulkan.1.dylib)
target_link_libraries(VulkanTesting /Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/lib/libvulkan.1.1.92.dylib)
# Don't know if I need the next two lines
link_directories(/usr/local/lib)
link_directories(/Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/lib)
The reason I showed the above file will become apparent in the question.
The 'Program' so far is the following:
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdexcept>
#include <functional>
#include <cstdlib>
#include <vector>
const int WIDTH = 800;
const int HEIGHT = 600;
class HelloTriangleApplication {
public:
void run() {
initWindow();
initVulkan();
mainLoop();
cleanup();
}
private:
GLFWwindow* window;
VkInstance instance;
void initWindow(){
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, "My first Vulkan window", nullptr, nullptr);
}
void initVulkan() {
createInstance();
}
void createInstance(){
// Instantiate Application Info
VkApplicationInfo applicationInfo = {};
applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
applicationInfo.pApplicationName = "Hello Triangle";
applicationInfo.applicationVersion = VK_MAKE_VERSION(1,0,0);
applicationInfo.pEngineName = "No Engine";
applicationInfo.engineVersion = VK_MAKE_VERSION(1,0,0);
applicationInfo.apiVersion = VK_API_VERSION_1_0;
// Instantiate Instance Creation Info
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &applicationInfo;
// Get GLFW platform specific extensions
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
// Fill in required extensions in Instance Creation Info
createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
// For validation layers, this is a later step in the tutorial.
createInfo.enabledLayerCount = 0;
// Create the Vulkan instance, and check if it was successful.
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
if(result != VK_SUCCESS){
std::cout << "glfwExtensionCount: " << glfwExtensionCount << "\n";
std::cout << "glfwExtensionNames: " << &glfwExtensions << "\n";
std::cout << "result: " << result << "\n";
throw std::runtime_error("Failed to create Vulkan Instance");
}
}
void mainLoop() {
while(!glfwWindowShouldClose(window)){
glfwPollEvents();
}
}
void cleanup() {
glfwDestroyWindow(window);
glfwTerminate();
}
};
int main() {
HelloTriangleApplication app;
try {
app.run();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
The problem I am having is that when I try to run the program, it will not create a VkInstance. The function returns VK_ERROR_INCOMPATIBLE_DRIVER. Now, I doubt that the driver is in fact incompatible as I have run the demo applications that came with the Vulkan SDK for one, and for another I have been able to run the exact same 'program' in XCode. When I investigated the problem a bit further, I noticed that the glfwGetRequiredInstanceExtensions function returns no extensions when the program is run in CLion like this, but does return one in the XCode equivalent.
This all leads me to believe that there is something I have done wrong in linking the libraries/frameworks in the Cmake file because I am aware of the fact that Vulkan is not directly supported in Mac OS, but instead (somehow?) passes through a layer to communicate with Metal.
Do I need to specify a way for the program to pass its Vulkan functionality through a Metal layer, and is this done automagically in XCode, or is there another problem with my approach?
Any help would be greatly appreciated!
You might want to look at the MacOS Getting Started Guide on the LunarXchange website and in your SDK. There is a section at the end that shows how to use CMake to build a Vulkan app and run it on MacOS. You also may want to use the FindVulkan CMake module instead of manually setting the include directories and the target link libraries.
But my first guess about your specific problem is that you may not be setting the VK_ICD_FILENAMES environment variable. You are correct in your observation that there is no direct support for Vulkan. Instead, the support is provided by the MoltenVK library which is treated as a Vulkan driver. But this "driver" is not installed in any system directory by the SDK. The SDK is just unzipped in your home directory structure, so you must tell the Vulkan loader where to find it via this environment variable.
Again, the CMake section at the end of the Getting Started Guide demonstrates the use of this environment variable. And the entire guide goes into additional detail about how the various Vulkan and MoltenVK components work.
I'm building an embedded python application in C++, using boost::python. The embedded environment exports part of itself as a module, in other words the python code that runs in the environment won't run in a standard python env as the embedded module can't be imported.
One of the features that would be really helpful for debugging would be a debug shell, where I can break out and manually input standard python expressions to inspect/modify the current state. The problem I have is that I don't/can't know in advance whether it's an eval (e.g. "2+2") or an exec (e.g. "a=2+2"). If I exec("2+2") I don't get the result, and if I eval("a=2+2") I get a syntax error. (Coming from a C background I don't quite understand why this distinction exists). Trying eval first, then exec if it fails, seems like a very dubious solution not least because of side effects.
As far as I can see boost::python simply replicates python's eval/exec functions, so this problem is more at the python level, but the answer I'm hoping to get is how to do it at the C++ (ideally boost) level. Is there some horrendously complicated regex that could be used to differentiate exec-able from eval-able code? For now I'm just going with the ugly solution of making the user decide with a prefix on the expression.
Here's an MCVE with a TODO at the point where I need to choose between eval and exec (obv. requires python-dev and boost_python libs)
// g++ $(python3-config --cflags) so.cpp -fPIC -lboost_python3 $(python3-config --ldflags)
#include <boost/python.hpp>
#include <string>
#include <iostream>
namespace py = boost::python;
std::string pyobject_to_string(PyObject* obj)
{
PyObject* repr = PyObject_Str(obj);
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
const char *bytes = PyBytes_AS_STRING(str);
Py_XDECREF(repr);
Py_XDECREF(str);
return std::string(bytes);
}
int main(int argc, const char** argv)
{
// Init python env
Py_Initialize();
if (argc < 2)
{
return 1;
}
try
{
// TODO decide, based on argv[1], which needs to be called, this:
py::object res = py::eval(argv[1]);
std::cout << pyobject_to_string(res.ptr()) << std::endl;
// or this:
py::exec(argv[1]);
// or something else entirely...?
}
catch(py::error_already_set&)
{
if (PyErr_Occurred())
{
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
std::string message = pyobject_to_string(type) + ":" + pyobject_to_string(value);
//PyErr_Restore(type, value, traceback);
std::cerr << message << std::endl;
}
else
{
std::cerr << "unknown error" << std::endl;
return 1;
}
}
}
Example output is:
$ ./a.out 2+2
4
$ ./a.out a=2+2
<class 'SyntaxError'>:('invalid syntax', ('<string>', 1, 2, 'a=2+2'))
Many thanks in advance
If I build an openCL Program from source code like this
cl::Program program = cl::Program(context, sourceCode);
program.build(devices);
I would like to check if this was successful. I saw a few examples of how to do this in C, but since my project ist in C++ I was wondering how to get (in case something goes wrong) a readable text message that indicates what might be the issue using the C++ wrapper.
I have also enabled exceptions
#define CL_HPP_ENABLE_EXCEPTIONS
but do not know if build(...) throws an exception.
I am using the AMD APP SDK 3.0 and the cl2.hpp from the Khronos webpage (as it was not included in the SDK).
The cl::Program::build() function does indeed throw an exception if the build fails. Here's how you can get the build log:
cl::Program program = cl::Program(context, sourceCode);
try
{
program.build(devices);
}
catch (cl::Error& e)
{
if (e.err() == CL_BUILD_PROGRAM_FAILURE)
{
for (cl::Device dev : devices)
{
// Check the build status
cl_build_status status = program.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(dev);
if (status != CL_BUILD_ERROR)
continue;
// Get the build log
std::string name = dev.getInfo<CL_DEVICE_NAME>();
std::string buildlog = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(dev);
std::cerr << "Build log for " << name << ":" << std::endl
<< buildlog << std::endl;
}
else
{
throw e;
}
}
Im using the latest SDL 2.0 version on Xubuntu 64-bits. I installed through the provided install script on the source code.
Compiling works well, however when trying to open a font or image (regardless of its extension), it will always fail to open.
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
int main (int argc, char *argvp[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
cout << SDL_GetError() << endl;
}
if (TTF_Init() == -1)
{
std::cout << TTF_GetError() << std::endl;
return 2;
}
TTF_Font *font1 = NULL;
font1 = TTF_OpenFont("SourceSansPro-Regular.ttf", 20);
if (font1 == NULL)
{
std::cout << "ERROR OPENING FONT = " << TTF_GetError() << std::endl;
}
TTF_CloseFont(font1);
SDL_Quit();
return 0;
}
I compiled with
g++ -Wall fontTEST.cpp -o TEST -lSDL2 -lSDL_ttf (NOTE that SDL_ttf installs as such, not as SDL2_ttf)
And get the following error: Failed to load font: 0 Couldn't load font file
This happens with images as well. I've already tried with different fonts and images, apparently it works if I compile with SDL 1.2, just not with 2.0.
Also why does the provided install script installs the lib and include folders in /user/local/?
I moved them to /usr/ but the problem persists.
Remember the following:
On Unix, file paths are case-sensitive
As said in Xonar's comment, tilde '~' expansion is a shell feature, it does not work in C/C++ programs, you should use the real path instead.
The strace log says clearly that something is wrong with the path.
You should try the following:
Rename your font file to "font.ttf"
put it in /home/user/font.ttf
use "/home/user/font.ttf" as the path in your code.