qt ip camera stream libvlc return values - c++

I am using Qt and libvlc to create a gui for an ip camera stream. After i finished it i started testing it against wrong values NULLs... etc. My problem is that when i give a wrong string as network link i dont get NULL as return values. A portion of the code is this
const char * const vlc_args[] = {
"--preferred-resolution=576",
"--network-caching=250",
"--no-audio"
};
my_vlcInstance = libvlc_new(3, vlc_args);
if (my_vlcInstance == NULL){
emit sendDebugMessage("Couldn't create vlc instance", "Red");
return;
}
my_LiveMedia = libvlc_media_new_location(my_vlcInstance, link.toStdString().c_str());
if (my_LiveMedia == NULL){
emit sendDebugMessage("Error installing media", "Red");
return;
}
my_LiveMediaPlayer = libvlc_media_player_new_from_media(my_LiveMedia);
if (my_LiveMediaPlayer == NULL){
emit sendDebugMessage("Error creating media player", "Red");
return;
}
now link is a QString containing the network link. I know that bad things happen as i can see the errors in the Visual studio debug window. "core input error: open of `dsfgdfgfg' failed" "Your input can't be opened" and stuff like that. So why cant i catch these errors?
Furthermore... when i push my start recording button a file is produced (corrupted obviously as there is no stream) and libvlc function calls dont return the errors as specified in the documentation. For this for example:
if (libvlc_media_player_play(my_LiveMediaPlayer) == 0){
emit sendDebugMessage("Live mode started successfully", "Green");
isLive = true;
}
So how do i catch the bad link?

I solved my problem with the libvlc_media_player_get_state function. I ignore the libvlc_media_player_play return value and i just poll the current state of the media player until i get a different state from IDLE/CLOSE and OPENING. On the bad links i get an ERROR state and on the correct links i get PLAYING state.

Related

X11 DestroyNotify event returns wrong window parameter

I'm currently working on writing a reparenting window manager using C++ and the XCB library. I unmanage windows when I recieve an UnmapNotify event; in this case the code is very simple:
if (unmap_ignore > 0) {
unmap_ignore--;
return;
}
client *cl = nullptr;
size_t idx = 0;
for (client &c : clients) {
if (c.window == ev->window) {
cl = &c;
break;
}
idx++;
}
if (!cl)
return;
xcb_unmap_window(conn, cl->frame);
clients.erase(clients.begin() + idx);
However, this does not work for some clients that don't bother unmapping the window (usually happens when you force kill the process). Then instead a DestroyNotify is sent. However the ev->window field there (typeof ev = xcb_destroy_notify_event_t) is some value that isn't what I want... here are some example logs (also note each line is a new DestroyNotify event, I get it twice for some reason and each time the #window field is different but not correct):
Found a client window: 4194307 but this was destroyed: 4194305
Found a client window: 4194307 but this was destroyed: 4194313
I remember before I tried to write a window manager in Xlib and had this exact same issue. I must be missing something obvious though, but if I look at the code of other reparenting window managers like Awesome or Herbsluftwm they just use the window field and have no problems. What am I doing wrong?
(my full code is here: http://ix.io/3yDj)
One thing I suspect is that it is just giving me two children windows of the destroyed parent instead of sending the actual parent. no idea why, but it is the most logical thing I can come up with. I just want to be able to handle this so I can unmap the frame for things that don't send UnmapNotify events.
I also first thought that it may report DestroyNotify on the parent window instead of the client reparented one, so I tried checking the frame but to no avail:
Found a client window: 2097152 but this was destroyed: 4194305
Found a client window: 2097152 but this was destroyed: 4194313
I've been truly stumped on this so any help is appreciated, thanks!
Awesome for example does the exact same thing as I tried with ev->window:
static void
event_handle_destroynotify(xcb_destroy_notify_event_t *ev)
{
client_t *c;
if((c = client_getbywin(ev->window)))
client_unmanage(c, CLIENT_UNMANAGE_DESTROYED);
else
for(int i = 0; i < globalconf.embedded.len; i++)
if(globalconf.embedded.tab[i].win == ev->window)
{
xembed_window_array_take(&globalconf.embedded, i);
luaA_systray_invalidate();
}
}

Setting Status icon for CFAPI does not work as expected

I try to set the status icon of the placeholder file created with CFAPI to error. (see below)
content of folder T:
I set the error state on the file, but it does not display the error. However the error is displayed on the containing folder.
I use following code to set the error on the file (the complete code is published on github):
void SetTransferStatus(_In_ PCWSTR fullPath, _In_ SYNC_TRANSFER_STATUS status)
{
// Tell the Shell so File Explorer can display the progress bar in its view
try
{
// First, get the Volatile property store for the file. That's where the properties are maintained.
winrt::com_ptr<IShellItem2> shellItem;
winrt::check_hresult(SHCreateItemFromParsingName(fullPath, nullptr, __uuidof(shellItem), shellItem.put_void()));
winrt::com_ptr<IPropertyStore> propStoreVolatile;
winrt::check_hresult(
shellItem->GetPropertyStore(
GETPROPERTYSTOREFLAGS::GPS_READWRITE | GETPROPERTYSTOREFLAGS::GPS_VOLATILEPROPERTIESONLY,
__uuidof(propStoreVolatile),
propStoreVolatile.put_void()));
// Set the sync transfer status accordingly
PROPVARIANT transferStatus;
winrt::check_hresult(
InitPropVariantFromUInt32(
status,
&transferStatus));
winrt::check_hresult(propStoreVolatile->SetValue(PKEY_SyncTransferStatus, transferStatus));
// Without this, all your hard work is wasted.
winrt::check_hresult(propStoreVolatile->Commit());
// Broadcast a notification that something about the file has changed, so that apps
// who subscribe (such as File Explorer) can update their UI to reflect the new progress
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, static_cast<LPCVOID>(fullPath), nullptr);
//wprintf(L"Succesfully Set Transfer Progress on \"%s\" to %llu/%llu\n", fullPath, completed, total);
}
catch (...)
{
// winrt::to_hresult() will eat the exception if it is a result of winrt::check_hresult,
// otherwise the exception will get rethrown and this method will crash out as it should
wprintf(L"Failed to Set Transfer Progress on \"%s\" with %08x\n", fullPath, static_cast<HRESULT>(winrt::to_hresult()));
}
}
In addition, if I delete the file and create a new file the state will still be on error.
Someone pointed me to an pull request in the windows cloud mirror sample that shows how to accomplish this.
This is the code:
void Utilities::UpdateErrorOnItem(PCWSTR path, bool setError)
{
try
{
winrt::com_ptr<IShellItem2> item;
winrt::check_hresult(SHCreateItemFromParsingName(path, nullptr, IID_PPV_ARGS(item.put())));
winrt::com_ptr<IPropertyStore> propertyStore;
winrt::check_hresult(item->GetPropertyStore(GPS_READWRITE | GPS_EXTRINSICPROPERTIESONLY, IID_PPV_ARGS(propertyStore.put())));
PROPVARIANT propVar{};
if (setError)
{
propVar.vt = VT_UI4;
propVar.ulVal = static_cast<unsigned long>(E_FAIL);
winrt::check_hresult(propertyStore->SetValue(PKEY_LastSyncError, propVar));
}
else
{
// Clear by setting to empty
propVar.vt = VT_EMPTY;
winrt::check_hresult(propertyStore->SetValue(PKEY_LastSyncError, propVar));
}
winrt::check_hresult(propertyStore->Commit());
}
catch (...)
{
// winrt::to_hresult() will eat the exception if it is a result of winrt::check_hresult,
// otherwise the exception will get rethrown and this method will crash out as it should
wprintf(L"Failed to set error state with %08x\n", static_cast<HRESULT>(winrt::to_hresult()));
}

Cannot set Scanner Capability because L_TwainStartCapsNeg returns error -84

I'm trying to use the Leadtools API version 21 for automatically scanning some documents and here is a sudo code of what I have done (it runs in a secondary thread and the unlock has been done in the main thread):
void CheckRetCode(int rc)
{
if (SUCCESS != rc)
{
L_TCHAR errMsg[1024];
memset(errMsg, 0, sizeof(errMsg));
L_GetFriendlyErrorMessage(rc, errMsg, 1024, L_FALSE);
throw TLeadException(errMsg, rc);
}
}
void OnThreadExecute(void)
{
HTWAINSESSION hSession = nullptr;
APPLICATIONDATA appData;
L_INT nRet;
L_TCHAR pszTwnSourceName[1024];
LTWAINSOURCE sInfo;
memset(&appData, 0, sizeof(APPLICATIONDATA));
appData.uStructSize = sizeof(APPLICATIONDATA);
appData.hWnd = hWnd;// hWnd is valid handle of my main window
appData.uLanguage = TWLG_ENGLISH_USA;
appData.uCountry = TWCY_USA;
wcscpy(appData.szManufacturerName, L"MyCompanyName");
wcscpy(appData.szAppProductFamily, L"MyProductName");
wcscpy(appData.szAppName, appData.szAppProductFamily);
wcscpy(appData.szVersionInfo, L"Version 0.1.0.1");
nRet = L_TwainInitSession2(&hSession, &appData, LTWAIN_INIT_MULTI_THREADED);
CheckRetCode(nRet);// the exception gets catched elsewhere but no error reported here
memset(pszTwnSourceName, 0, sizeof(pszTwnSourceName));
wcscpy(pszTwnSourceName, L"EPSON Artisan837/PX830"); // the name of the scanner is verifyed
sInfo.uStructSize = sizeof(LTWAINSOURCE);
sInfo.pszTwainSourceName = pszTwnSourceName;
CheckRetCode(L_TwainSelectSource(hSession, &sInfo)); // No error reported here
CheckRetCode(L_TwainStartCapsNeg(hSession)); // in here I get the return value -84 which is reported as "TWAIN DS or DSM reported error, app shouldn't (no need for your app to report the error)."
// the rest of the code but we cannot get there since above code reports error
}
Can anyone tell me what I'm doing wrong? Is there a step that I'm missing here?
EditThe function L_TwainSelectSource() make no effort to make sure the supplied source is valid and does not even return an error. As result, if you set the selected source to a garbage name, it will act as if it accepted it. From that point on if you try to Get/Set anything or try to acquire an image, every function returns -84.
Thank you
Sam
To test your code, I put the main window’s handle in a global variable:
globalhWnd = hWnd;
And modified your function to use that handle like this:
void OnThreadExecute(void *)
{
...
appData.hWnd = globalhWnd; // hWnd is valid handle of my main window
...
}
Then created a thread for it from the main program like this:
globalhWnd = hWnd;
_beginthread(OnThreadExecute, 0, 0);
I tried this with 5 different Twain sources: 2 virtual and 3 physical scanners (one of them an old Epson). All 5 drivers returned SUCCESS when calling L_TwainStartCapsNeg() from within the thread.
Two possibilities come to mind:
The problem might be caused by something else in your code other than the thread function.
Or the problem could be specific to your Twain driver.
To rule out the first possibility, I suggest creating a small test project that only creates a similar thread and does nothing else and trying it with different scanners. If it causes the same problem with all scanners, send that test project (not your full application) to support#leadtools.com and our support engineers with test it for you.
If the problem only happens with a specific Twain driver, try contacting the scanner’s vendor to see if they have an updated driver.

Why can't webrtc find the capturer it suggested?

I'm creating a webrtc-based voip app for windows in C++. I'm trying to initialize a peerconnection. I'm stuck at the part to fetch a camera. I'm using the following code to find a camera to start streaming media from (copied from the peerconnection client example):
rtc::scoped_ptr<cricket::DeviceManagerInterface> dev_manager(cricket::DeviceManagerFactory::Create());
if (!dev_manager->Init()) {
LOG(LS_ERROR) << "Can't create device manager";
return NULL;
}
std::vector<cricket::Device> devs;
if (!dev_manager->GetVideoCaptureDevices(&devs)) {
LOG(LS_ERROR) << "Can't enumerate video devices";
return NULL;
}
std::vector<cricket::Device>::iterator dev_it = devs.begin();
cricket::VideoCapturer* capturer = NULL;
for (; dev_it != devs.end(); ++dev_it) {
capturer = dev_manager->CreateVideoCapturer(*dev_it);
if (capturer != NULL)
break;
}
capturer is empty after this procedure. I stepped through the code to see what was wrong. dev_manager is succesfully intialized, devs gets a single entry (my webcam) with a name:
"logitech HD webcam c270"
And an id:
"\\\\?\\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}"
But after the CreateVideoCapturer() call, capturer is still empty. I get a warning in the console saying:
Warning(webrtcvideocapturer.cc:175): Failed to find capturer for id: \\?\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}
I checked if the id I get in devs and this one match and they do. The entire log for my app can be found in this pastebin. As you can see, right after trying to assign the camera as capturer and failing, the app crashes on an assert(capturer != NULL) call somewhere in videosource.cc.
The camera is not in use, nor is it defect. The peerconnection client example works perfectly and uses the same code. I think I'm missing some step in the initialization of webrtc, but I can't find which step.
edit with additional info
I'm debug stepping through the library now. In webrtcvideocapturer.cc around line 160 is the following code:
int num_cams = info->NumberOfDevices();
char vcm_id[256] = "";
bool found = false;
for (int index = 0; index < num_cams; ++index) {
char vcm_name[256];
int32 i = info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name), vcm_id, ARRAY_SIZE(vcm_id));
if (i != -1) {
if (device.name == reinterpret_cast<char*>(vcm_name)) {
found = true;
break;
}
}
}
if (!found) {
LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
factory_->DestroyDeviceInfo(info);
return false;
}
There are two problems with this part. First of all, if I step into info->NumberOfDevices() it shows me that that function's only content is the line return 0;. I tried hard-coding 1 there, to at least get into the for loop. Then when I step into the info->GetDeviceName() call it shows me that the content of that function is return -1;.
These two functions are meant to be implemented by a class that inherits from webrtc::VideoCaptureModule::DeviceInfo, so there is clearly something not initialized that does needs to be initialized. What do I still need to do before trying to get a camera?
What libraries did you link?
Because Google WebRTC source codes are changing rapidly, it is difficult to track down issues to the source level.
But I remember the almost same problem occurred when I accidentally linked external capture module library (video_capture_module_impl ??) or (I'm not sure) omitted internal impl (video_capture_module_internal_impl ??).

Download a single .txt using QFtp

I've got a problem with QFtp. I wanna download a single .txt file with a single line(8 bytes) from my server, so I've written the following code, but it doesn't work.
The file "actions.txt" were created in the folder1 directory. I can see the size of it pretty well in the client-side. But the file is not being written. I'm getting an empty file.
QFile* actionFile = new QFile("action.txt");
QFtp *ftp = new QFtp(parent);
void Dialog::getActionFile()
{
actionFile->open(QIODevice::WriteOnly);
ftp->connectToHost("mydomain.de");
ftp->login("user", "pw");
ftp->cd("folder1");
ftp->get("action.txt",actionFile);
ftp->close();
actionFile->close();
}
Thanks in advance.
The documentation of several methods of QFtp says:
The function does not block and returns immediately. The command is
scheduled, and its execution is performed asynchronously. The function
returns a unique identifier which is passed by commandStarted() and
commandFinished().
So you need to wait for the appropriate signals to be emitted.
Note that you can also use QNetworkRequest to request the whole ftp URL (I think even with username and password inside the URL) to download the file.
I solved my problem.
I treated one step each time the commandFininshed signal was emitted.
like this:
void MainWindow::ftpCommandFinished(int id, bool error)
{
static bool flag = false;
if(ftp->currentCommand() == QFtp::ConnectToHost)
checkUpdate();
if(ftp->currentCommand() == QFtp::Get)
{
file->close();
if(error)
{
QMessageBox::warning(this, "Erro!", ftp->errorString());
deleteLater();
return;
}
if(!flag)
checkVersion();
else{
delete ftp, file;
ftp = 0; file = 0;
}
flag = true;
}
}
the reason of the flag variable is something else that needs further explanations about the program, so i won't go down that road.
Thanks for you help. It somehow helped me a lot.