Please help with this beginner's program for fetching gdk screen attributes. I have a small C++ program to find out the connected display units. I am using c++ on Linux Debian. gdk_screen_get_default() doesn't return Screen object. If I don't check for screen object then the following error occurs.
Error
(process:8023): Gdk-CRITICAL **: gdk_screen_get_monitor_geometry: assertion 'GDK_IS_SCREEN (screen)' failed
I went through related posts and referred to this for the below code snippet.
Thanks for your help. Any pointers/guidelines to resolve this would be helpful.
I have one monitor connected and the display settings are
$ echo $XDG_CURRENT_DESKTOP
GNOME
$ echo $DISPLAY
:0
CODE
#include <gdk/gdk.h>
#include <iostream>
/*
GTK version 3.14.5
g++ getScreenInfo.cpp -o getScreenInfo `pkg-config gtk+-3.0 --cflags --libs`
*/
int main()
{
GdkScreen *screen;
screen = gdk_screen_get_default();
int num_monitors;
int i;
if (screen)
{
num_monitors = gdk_screen_get_n_monitors(screen);
for (i = 0; i < num_monitors; i++)
{
GdkRectangle rect;
gdk_screen_get_monitor_geometry (screen, i, &rect);
std::cout << "monitor " << i << ": coordinates (" << rect.x << ","
<< rect.y << ", size (" << rect.width << "," << rect.height << ")"
<< std::endl;
}
}else
{
std::cout << "Couldn't obtain default screen object" << std::endl;
}
}
27 Apr 2017 EDIT: RESOLVED
#include <iostream>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
/*
GTK version 3.14.5
To compile:
g++ getScreenInfo.cpp -o getScreenInfo `pkg-config gtk+-3.0 --cflags --libs`
*/
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GdkScreen *screen = gdk_screen_get_default();
int num_monitors;
int i;
if (screen)
{
num_monitors = gdk_screen_get_n_monitors(screen);
for (i = 0; i < num_monitors; i++)
{
GdkRectangle rect;
gdk_screen_get_monitor_geometry (screen, i, &rect);
std::cout << "monitor " << i << ": offsets (" << rect.x << ","
<< rect.y << ", size (" << rect.width << "," << rect.height << ")"
<< std::endl;
}
}
else
{
std::cout << "Couldn't obtain default screen object" << std::endl;
}
// To query primary display properties
guint monitor = gdk_screen_get_primary_monitor(screen);
GdkRectangle screen_geometry = { 0, 0, 0, 0 };
gdk_screen_get_monitor_geometry(screen, monitor, &screen_geometry);
std::cout << screen_geometry.x << std::endl;
std::cout << screen_geometry.y << std::endl;
std::cout << screen_geometry.width << std::endl;
std::cout << screen_geometry.height << std::endl;
}
Answering my own question.
Finally, figured out the resolution. gtk_init( ) was missing before fetching the screen. Added that and respective include for gtk/gtk.h and now the code looks like
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv); // <---- added this
GdkScreen *screen = gdk_screen_get_default();
:
followed by rest of the code shared in the problem description above.
Related
Given the following code:
#include <SDL2/SDL.h>
#include <SDL2/SDL_audio.h>
#include <iostream>
#include <chrono>
#include <thread>
static void SDLCallback(void *userData, Uint8 *data, int bytes) {
std::cerr << "SDLCallback: " << bytes / sizeof(float) << "\n";
}
int main() {
using namespace std::literals;
SDL_Init(SDL_INIT_AUDIO);
SDL_AudioDeviceID m_deviceId{};
SDL_AudioSpec m_desired, m_obtained;
m_desired.freq = 48000;
m_desired.format = AUDIO_F32SYS;
m_desired.channels = 2;
m_desired.samples = 1024;
m_desired.callback = SDLCallback;
m_desired.userdata = nullptr;
m_deviceId = SDL_OpenAudioDevice(nullptr, 0, &m_desired, &m_obtained, 0);
std::cerr << "SDL device: " << m_deviceId << std::endl;
if (m_deviceId < 2) {
std::cerr << "SDL: Couldn't open audio: " << SDL_GetError() << std::endl;
exit(1);
}
std::cerr << "rate: " << m_obtained.freq << "\n";
std::cerr << "samples: " << m_obtained.samples << "\n";
std::cerr << "bytes: " << m_obtained.size << "\n";
std::cerr << "channels: " << (int)m_obtained.channels << "\n";
SDL_PauseAudioDevice(m_deviceId, 0);
for (int i = 0; i < 10; i++) {
std::this_thread::sleep_for(100ms);
std::cerr << (SDL_GetAudioDeviceStatus(m_deviceId) == SDL_AUDIO_PLAYING)
<< std::endl;
}
SDL_CloseAudioDevice(m_deviceId);
SDL_Quit();
}
I am seeing the following output:
$ ./a.out
SDL device: 2
rate: 48000
samples: 1024
bytes: 8192
channels:
SDLCallback: 2048
SDLCallback: 2048
1
1
1
1
1
1
1
1
1
1
<program gets stuck on SDL_CloseAudioDevice>
That is, the SDLCallback function is called only twice at the beginning then not anymore, yet the audio is still marked as running. I am using PulseAudio.
What can I do to prevent that ? Where is my program wrong ? It works if I kill PulseAudio, but PulseAudio works fine for all my other software.
And if it is not wrong, how can I make sure that my users will never encounter that issue ? How can I recover without getting the program stuck on SDL_CloseAudioDevice ? As PulseAudio is very common among Linux users.
Currently started to work with qt and found some bug in my code, and I can't understand where it comes from. Maybe you will see and explain why it happens.
Here is main.cpp code part which changes shutter from 3000 to maximum:
if (camera.test_cam->liveFrameReady())
{
camera.visualizeFrame(camera.test_cam->liveFrame());
camera.set_shutter(0, 1, 3000 + i * 200);
controlWidget->update(camera.test_cam->liveFrame());
i++;
}
The code works slowly(1 fps ), because of the camera.visuzlizeFrame() method:
void OsCam::visualizeFrame(Common::FrameHandle hFrame)
{
void* buffer_ptr = this->getFrameData(hFrame);
int width = hFrame->dataType()->width();
int height = hFrame->dataType()->height();
cv::Mat m(height, width, CV_8UC3, (int*)buffer_ptr);
cv::imshow("test image", m);
cv::waitKey(1);
}
Gui interface shows the camera frame in real time, test image from visualizeFrame at the background
Actionally, I don't need to call this method (I used it just to be sure that I can read the memory and I used opencv because I am more familiar with it).
But if I get rid of this camera.visuzlizeFrame() my gui becomes white and does not give any response.
Even if I use cv::waitKey or Sleep functions, nothing happens to the gui.
void ControlWidget::update(Common::FrameHandle hFrame)
{
try
{
QImage img((uchar*)hFrame->buffer()->data(), hFrame->dataType()->width(), hFrame->dataType()->height(), QImage::Format::Format_RGB888);
QSize standart_size = QSize(hFrame->dataType()->width() / 3, hFrame->dataType()->height() / 3);
QPixmap rectPxmp = QPixmap::fromImage(img).scaled(standart_size);
this->camera_1->setPixmap(rectPxmp);
this->camera_2->setPixmap(rectPxmp);
cv::waitKey(300);
}
catch (GeneralException& e)
{
std::cout << e.what() << std::endl;
}
}
Shall I go to QThreads? One thread for reading the buffer and another one for visualization of gui?
Thank you!
some additional code:
void* OsCam::getFrameData(Common::FrameHandle hFrame)
{
bool displayFrameData = false;
void* pFrameData = NULL;
try
{
if (hFrame)
{
if (displayFrameData)
{
// display information about the frame
cout << "Frame index: " << hFrame->frameIndex();
cout << "Frame timestamp: " << hFrame->timestamp();
// display information about the frame "data type"
DataTypeHandle hDataType = hFrame->dataType();
cout << "Frame size in bytes: " << hDataType->frameSizeInBytes() << endl;
cout << "Width in pixels: " << DataType::width(hDataType) << endl;
cout << "Height in rows: " << DataType::height(hDataType) << endl;
cout << "Bit depth: " << DataType::bitDepth(hDataType) << endl;
cout << "Bytes/line (stride): " << DataType::stride(hDataType) << endl;
// display the frame video format
VideoDataType::Format videoFormat = VideoDataType::format(hDataType);
cout << "Video format: " << VideoDataType::formatString(videoFormat).c_str() << endl;
// get a pointer to the frame data
}
pFrameData = hFrame->buffer()->data();
}
}
catch (GeneralException& e)
{
cout << e.what() << endl;
}
return pFrameData;
}
and main (I changed it a little bit) :
int main(int argc, char **argv)
{
QApplication app(argc, argv);
ControlWidget *controlWidget = new ControlWidget;
//controlWidget->show();
try
{
OsCam camera;
int i = 0;
for (int j = 0; j<10000 ; j++)
{
if ((camera.test_cam->liveFrameReady()))
{
Common::FrameHandle loaded = camera.test_cam->liveFrame()->clone();
camera.visualizeFrame(loaded);
controlWidget->update(loaded);
camera.set_shutter(0, 1, 3000 + i * 200);
loaded->~Frame();
}
i++;
}
}
catch (GeneralException& e)
{
std::cout << e.what() << std::endl;
int a;
std::cin >> a;
return 1;
}
}
After cv::named_window
In my application I am using a Gtk::DrawingArea like this:
Window win;
DrawingArea area;
Box box(ORIENTATION_VERTICAL);
area.signal_realize().connect(sigc::ptr_fun(&on_video_area_realize));
box.pack_start(myWidgets, true, true);
box.pack_start(area, false, false);
win.add(box);
win.show_all();
The problem is, the function on_video_area_realize is not being called and if I query the status of the DrawingArea with area.get_realized(), it is false, so it has not been realized yet.
I do not understand why it has not been realized? As far as I understand, a widget is realized when it is added to a window - which, as far as I think, I am doing already.
The realize signal happens when the window (and its children) is showed. The following code (I tested this with Gtkmm 3.24.20):
#include <iostream>
#include <gtkmm.h>
void on_video_area_realize()
{
std::cout << "Video drawing area realized!" << std::endl;
}
int main(int argc, char *argv[])
{
std::cout << "Gtkmm version : " << gtk_get_major_version() << "."
<< gtk_get_minor_version() << "."
<< gtk_get_micro_version() << std::endl;
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
Gtk::Window window;
Gtk::Box layout{Gtk::ORIENTATION_VERTICAL};
Gtk::Label label{"Example"};
std::cout << "Checkpoint 1" << std::endl;
Gtk::DrawingArea area;
std::cout << "Checkpoint 2" << std::endl;
area.signal_realize().connect(sigc::ptr_fun(&on_video_area_realize));
std::cout << "Checkpoint 3" << std::endl;
layout.pack_start(label, true, true);
layout.pack_start(area, false, false);
std::cout << "Checkpoint 4" << std::endl;
window.add(layout);
window.show_all();
std::cout << "Checkpoint 5" << std::endl;
return app->run(window);
}
Yields the following output:
Gtkmm version : 3.24.20
Checkpoint 1
Checkpoint 2
Checkpoint 3
Checkpoint 4
Video drawing area realized!
Checkpoint 5
From this, we can see that the drawing area is realized, but not when added to the window.
I've been attempting to use angelscript and I keep getting linker errors, however if I put a reference to pthread_exit(NULL) at the end of my main function it builds, links, and runs normally.
Here is the code in question:
#include <iostream>
#include <angelscript.h>
#include <cassert>
// This is used for AngelScript error messages
void MessageCallback(const asSMessageInfo &msg)
{
const char *type = "ERR ";
if( msg.type == asMSGTYPE_WARNING )
{
type = "WARN";
}
else if( msg.type == asMSGTYPE_INFORMATION )
{
type = "INFO";
}
std::cout << msg.section << " (" << msg.row << ", " << msg.col << ") : " << type << " : " << msg.message << std::endl;
}
int main(void)
{
asIScriptEngine* engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
int r = engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
assert(r >= 0);
std::cout << "Testing" << std::endl;
engine->Release();
pthread_exit(NULL);
return 0;
}
and this is the command line:
g++ -Wl,-O1,--sort-common,--as-needed,-z,relro -Wl,-O1 -o fib main.o -langelscript -lpthread
any ideas?
when i run the compieled .exe-file it shows the commandline, and I wish to remove it.. But I don't know nothing about C++, so I wonder how one can do it?
This is not my script... Just so you know.
#include <iostream>
#include <windows.h>
using namespace std;
typedef long (*GetFunctionCount) (void) __attribute__((stdcall));
typedef long (*GetFunctionInfo)(int, void*&, char*&) __attribute__((stdcall));
typedef void (*Setup)(char*,char*,long,long,char*) __attribute__((stdcall));
int main(int argc, char** argv) {
HMODULE libsmart = LoadLibrary("./libsmart.dll");
cout << "Library: " << libsmart << '\n';
cout << "GetFunctionCount: " << (void*)GetProcAddress(libsmart, "GetFunctionCount") << '\n';
cout << "GetFunctionInfo: " << (void*)GetProcAddress(libsmart, "GetFunctionInfo") << '\n';
GetFunctionCount count = (GetFunctionCount) GetProcAddress(libsmart, "GetFunctionCount");
GetFunctionInfo info = (GetFunctionInfo) GetProcAddress(libsmart, "GetFunctionInfo");
int exports = count();
cout << "#Exports = " << count() << '\n';
for (int i = 0; i < exports; i++) {
char* def = new char[1024];
void* addr;
info(i,addr,def);
cout << '\t' << addr << " = " << def << '\n';
delete def;
}
cout << "Starting SMART...\n";
Setup setup = (Setup) GetProcAddress(libsmart, "std_setup");
setup((char*)"http://world19.runescape.com/", (char*)",f5", 765, 503,(char*)"");
while (true) Sleep(1000);
return 0;
}
#define _WIN32_WINNT 0x0500
#include <iostream>
#include <windows.h>
using namespace std;
typedef long (*GetFunctionCount) (void) __attribute__((stdcall));
typedef long (*GetFunctionInfo)(int, void*&, char*&) __attribute__((stdcall));
typedef void (*Setup)(char*,char*,long,long,char*) __attribute__((stdcall));
int main(int argc, char** argv) {
HWND hWnd = GetConsoleWindow();
ShowWindow( hWnd, SW_HIDE );
HMODULE libsmart = LoadLibrary("./libsmart.dll");
cout << "Library: " << libsmart << '\n';
cout << "GetFunctionCount: " << (void*)GetProcAddress(libsmart, "GetFunctionCount") << '\n';
cout << "GetFunctionInfo: " << (void*)GetProcAddress(libsmart, "GetFunctionInfo") << '\n';
GetFunctionCount count = (GetFunctionCount) GetProcAddress(libsmart, "GetFunctionCount");
GetFunctionInfo info = (GetFunctionInfo) GetProcAddress(libsmart, "GetFunctionInfo");
int exports = count();
cout << "#Exports = " << count() << '\n';
for (int i = 0; i < exports; i++) {
char* def = new char[1024];
void* addr;
info(i,addr,def);
cout << '\t' << addr << " = " << def << '\n';
delete def;
}
cout << "Starting SMART...\n";
Setup setup = (Setup) GetProcAddress(libsmart, "std_setup");
setup((char*)"http://world19.runescape.com/", (char*)",f5", 765, 503,(char*)"");
while (true) Sleep(1000);
return 0;
}
Should work. Don't forget the definition at the top.
If you wish to remove the part that shows the commandline, any line that starts with cout << is showing something to the screen.
However, the command line is primarily stored in argv, and I don't see any reference to that in your program.
You will want to compile and link it to the windows subsystem, rather than the console subsystem.