How can i make that in the List codec's it will also show me the type of each codec? - c++-cli

The type of each codec or the type of the codec's
In the List i have in the end about 500 codec's i want that for example in the List in the beginning it will show for example:
Audio
mpeha
mpegv
.....
Video
xvid
divx
And so on.
The first two functions to get the List of codec's are in C:
const char* Encoder_GetNextCodecName()
{
current_codec = av_codec_next(current_codec);
while (current_codec != NULL)
{
return current_codec->name;
}
return "";
}
const char* Encoder_GetFirstCodecName()
{
current_codec = NULL;
return Encoder_GetNextCodecName();
}
Then i have header file:
const char* Encoder_GetNextCodecName();
const char* Encoder_GetFirstCodecName();
Then another C++ header file where i create the List:
List<String^> ^GetCodecs()
{
List<String^> ^l = gcnew List<String^>;
String ^s = gcnew String(Encoder_GetFirstCodecName());
while (!String::IsNullOrEmpty(s))
{
l->Add(s);
s = gcnew String(Encoder_GetNextCodecName());
}
return l;
}
Then when i'm doing in CSHARP this:
List<string> l = new List<string>(f.GetCodecs());
I see that the variable l containing 506 codec's .
The codec's are of ffmpeg !!!
Now in the C file there is also something like:
current_codec->type
Which have many properties.
And there is also something like this in the C file:
AVMediaType::
Which give me a 7 categories of types of the codec's.
The problem is how do i make in the C++ header file when i create the List that the List will be with the types of each codec or of each group of codec's like : Audio,Video,Data.... ?
EDIT
This is another header file i have that is connecting between the C functions and the CLI:
I have another header file where i first call the functions from C:
ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
bool Encoder_MoveToNextCodec();
bool Encoder_MoveToFirstCodec();
const char* Encoder_GetCurrentCodecName();
int Encoder_GetCurrentCodecType();
#ifdef __cplusplus
} // extern "C"
#endif
This is my CLI code:
#pragma once
// FFMPEG_WRAPPER.cpp : Defines the exported functions for the DLL application.
//
#include "ENCODER.h"
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal.h>
#include <vcclr.h>
#include <cstdlib>
#include <Windows.h>
using namespace System;
using namespace System::Drawing;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Drawing::Imaging;
using namespace msclr::interop;
namespace MyVideo
{
public ref class FFMPEGWrapper
{
public:
FFMPEGWrapper(void)
{
Encoder_init();
}
ref class CodecInfo
{
public:
String^ CodecName;
int CodecType;
};
List<CodecInfo^> ^GetCodecs()
{
List<CodecInfo^> ^l = gcnew List<CodecInfo^>;
bool KeepLooping = Encoder_MoveToFirstCodec();
while (KeepLooping)
{
CodecInfo ^codec = gcnew CodecInfo();
codec->CodecName = gcnew String(Encoder_GetCurrentCodecName());
codec->CodecType = Encoder_GetCurrentCodecType();
l->Add(codec);
KeepLooping = Encoder_MoveToNextCodec();
}
return l;
}
Then in CSHARP i did:
List<f.CodecInfo> l = f.GetCodecs();
But CodecInfo is not exist and i'm getting an error on the GetCodecs()
Error 1 Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
Error 2 'ScreenVideoRecorder.Form1.f' is a 'field' but is used like a 'type'
The problems the errors are in CSHARP.

You need to expand your C code to expose the extra details you want, eg:
__declspec(thread) AVCodec* current_codec = NULL;
bool Encoder_MoveToNextCodec()
{
current_codec = av_codec_next(current_codec);
return (current_codec != NULL);
}
bool Encoder_MoveToFirstCodec()
{
current_codec = NULL;
return Encoder_MoveToNextCodec();
}
const char* Encoder_GetCurrentCodecName()
{
if (current_codec != NULL)
return current_codec->name;
return "";
}
int Encoder_GetCurrentCodecType()
{
if (current_codec != NULL)
return (int) current_codec->type;
return AVMEDIA_TYPE_UNKNOWN;
}
Then expand your CLI code to store that info:
ref class CodecInfo
{
public:
String^ CodecName;
int CodecType;
...
};
List<CodecInfo^> ^GetCodecs()
{
List<CodecInfo^> ^l = gcnew List<CodecInfo^>;
bool KeepLooping = Encoder_MoveToFirstCodec();
while (KeepLooping)
{
CodecInfo ^codec = gcnew CodecInfo();
codec->CodecName = gcnew String(Encoder_GetCurrentCodecName());
codec->CodecType = Encoder_GetCurrentCodecType();
...
l->Add(codec);
KeepLooping = Encoder_MoveToNextCodec();
}
return l;
}
Then lastly, use the new info as needed:
List<CodecInfo> l = f.GetCodecs();
foreach(CodecInfo codec in l)
{
// use codec.CodecName, codec.CodecType, ... as needed
}

Related

Simple parsing to a tuple fails

Why does this not compile? The marked line gives me: "static assertion failed: The parser expects tuple-like attribute type". I would think that an std::tuple were the essence of "tuple-like"?
#include <string>
#include <tuple>
#include <boost/spirit/home/x3.hpp>
void parseInteger(std::string input) {
namespace x3 = boost::spirit::x3;
auto iter = input.begin();
auto end_iter = input.end();
int result;
x3::parse(iter, end_iter, x3::int_, result);
}
void parseIntegerAndDouble(std::string input) {
namespace x3 = boost::spirit::x3;
auto iter = input.begin();
auto end_iter = input.end();
std::tuple<int, double> result;
x3::parse(iter, end_iter, x3::int_ >> ' ' >> x3::double_, result); //Compile error!
}
int main(int, char **)
{
parseInteger("567");
parseIntegerAndDouble("321 3.1412");
return 0;
}
The trick is to include two additional header files:
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/std_tuple.hpp>
This is a bit more magical than I like, but I've got a feeling I really don't want to know how this works!

Integrate boost-asio with file descriptor based socket api from KDB+

I'm relatively new to boost-asio and I'm wondering if it's possible to make it work with KDB+ api here.
I tried something like the below but it doesn't seem to work properly,
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#define KXVER 3
#include "kx/k.h"
using boost::asio::ip::tcp;
namespace posix = boost::asio::posix;
class Feedhandler
{
public:
Feedhandler(boost::asio::io_service &io_service) : m_qsvc(io_service) {
char host[] = "localhost";
int port = 6812;
m_fd = khpu(host, port, "user:pass");
m_qsvc.assign(m_fd);
start_operations();
K ret = k(m_fd, ".u.sub", ks(""), ks(""), (K)0);
}
void start_operations()
{
boost::asio::async_read(m_qsvc, boost::asio::null_buffers(),
boost::bind(&Feedhandler::handle_read, this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_read(const boost::system::error_code& error, size_t size)
{
K data = k(m_fd,(S)0);
start_operations();
}
private:
int m_fd;
posix::stream_descriptor m_qsvc;
};
int main(int argc, char* argv[])
{
boost::asio::io_service io_service;
Feedhandler fh(io_service);
io_service.run();
return 0;
}
The handle_read method gets hit once and then subsequently there's no more call-backs.
Actually, it's better to use async_wait instead of async_read, like below,
m_qsvc.async_wait(boost::asio::posix::stream_descriptor::wait_read,
boost::bind(&Feedhandler::handle_read, this, boost::asio::placeholders::error) );

read multiple files with quite similar names c++

I am reading a file from current directory
ifstream myfile;
myfile.open("version1.1.hex");
Now a situation is arising that if user updates version then there will be version1.2.hex or version1.3.hex ..so on in the current directory, but one file at a time will be present. I want to write a code now which will cater this future need of reading different file.
I'm writing this code in C++/CLI.
Since file listings are a bit environment-dependant I am not sure if this is helpful to you,
but here is an example how to achieve your goal under the mircosoft regime.
What is needed is the FindFirstFile / FindNextFile calls which query all files matching the fileSearchKey. Then you can use the cFileName part of WIN32_FIND_DATAA as parameter to your open command
string fileSearchKey = "version*";
WIN32_FIND_DATAA fd;
bool bFirstRun = true;
bool bFinishedRun = false;
HANDLE h = INVALID_HANDLE_VALUE;
while (!bFinishedRun)
{
if (bFirstRun)
{
h = FindFirstFileA(fileSearchKey.c_str(), &fd);
bFirstRun = false;
} else
{
if (FindNextFileA(h, &fd) != FALSE)
{
// Abort with error because it has more than one file or decide for the most recent version
} else
{
bFinishedRun = true;
}
}
}
// Load file
ifstream myfile;
myfile.open(fd.cFileName);
This code will look in the directory and take the first file, then quit.
WARNING : this will work only on linux
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <cstring>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
using namespace std;
int main ()
{
char n[20];
unsigned char isFolder = 0x4;
unsigned char isFile = 0x8;
DIR *dir;
struct dirent *ent;
dir = opendir ("./");
if (dir != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
//folder sign
if(ent->d_type != isFolder && string(ent->d_name).find("version") != string::npos)
{
cout <<ent->d_name <<"\n";
// Your code
break;
}
}
closedir (dir);
} else {
/* could not open directory */
perror ("");
return 0;
}
cout << "=========" << endl;
}
In C++/CLI you should use the .net framework libraries for this. For instance you can use Directory::GetFiles.
using namespace System;
using namespace System::IO;
int main(array<System::String ^> ^args)
{
array<String^>^dirs = Directory::GetFiles(".", "version1.*.hex");
Collections::IEnumerator^ myEnum = dirs->GetEnumerator();
while (myEnum->MoveNext())
{
Console::WriteLine(myEnum->Current);
}
return 0;
}

System::String^ to TCHAR*

I have a class which collects all paths to .txt files of a given folder and stores them into a vector. Most of the functions I use require the usage of TCHAR* to get/set current directory and so on.
The class looks like this:
typedef std::basic_string<TCHAR> tstring;
class folderManager
{
private:
TCHAR searchTemplate[MAX_PATH];
TCHAR directory[MAX_PATH];
WIN32_FIND_DATA ffd;
HANDLE hFind;
vector<tstring> folderCatalog;
vector<tstring> fileNames;
bool succeeded;
public:
// get/set methods and so on...
};
// Changed TCHAR* dir to tstring dir
void folderManager::setDirectory(tstring dir)
{
HANDLE hFind = NULL;
succeeded = false;
folderCatalog.clear();
fileNames.clear();
// Added .c_str()
SetCurrentDirectory(dir.c_str());
GetCurrentDirectoryW(MAX_PATH, directory);
TCHAR fullName[MAX_PATH];
StringCchCat(directory, MAX_PATH, L"\\");
StringCchCopy(searchTemplate, MAX_PATH, directory);
StringCchCat(searchTemplate, MAX_PATH, L"*.txt");
hFind = FindFirstFile(searchTemplate, &ffd);
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
FindClose(hFind);
return;
}
do
{
StringCchCopy(fullName, MAX_PATH, directory);
StringCchCat(fullName, MAX_PATH, ffd.cFileName);
folderCatalog.push_back(fullName);
fileNames.push_back(ffd.cFileName);
}
while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
succeeded = true;
}
This is where I need to do the conversion of System::String^ to TCHAR*
private: System::Void dienuFolderisToolStripMenuItem_Click(System::Object^
sender, System::EventArgs^ e)
{
FolderBrowserDialog^ dialog;
dialog = gcnew System::Windows::Forms::FolderBrowserDialog;
System::Windows::Forms::DialogResult result = dialog->ShowDialog();
if (result == System::Windows::Forms::DialogResult::OK)
{
// Conversion is now working.
tstring path = marshal_as<tstring>(dialog->SelectedPath);
folder->setDirectory(path);
}
}
marsha_as "Performs the marshaling on a specific data object to convert it between a managed and a native data type".
Here there is the table for possible type conversion.
I use it this way:
marshal_as<std::wstring>(value)
TCHAR can be char or wchar_t, both of them present in marshal_as specialization, I suppose you need to point TCHAR* as template parameter:
TCHAR* result = marshal_as<TCHAR*>(value)
Actually MSDN says that you have to use it this way:
#include <msclr\marshal.h>
using namespace System;
using namespace msclr::interop;
int main(array<System::String ^> ^args)
{
System::String^ managedString = gcnew System::String("Hello World!!!");
marshal_context ^ context = gcnew marshal_context();
const wchar_t* nativeString = context->marshal_as<const wchar_t*>(managedString);
//use nativeString
delete context;
return 0;
}

How do I setup Using Systems::IO::Ports in DLL so that it can be called from a loadlibrary function

Using vc2012 express c++
I am a little confused on how a runtime library works, but I had needed to create one for a driver from some hardware I have so that it can be used in a SDK.
My source code is as follows
#include "PhantomAdapter.h"
#include <stdexcept>
int ready()
{
//return Comms::SerialPort::check();
return 1;
}
int open()
{
int flag=0;
//flag=Comms::SerialPort::openPort();
return flag;
}
int close()
{
Comms::SerialPort::closePort();
return 1;
}
int angle(double& angle)
{
angle = Comms::SerialPort::read();
return 0;
}
int torque(double torque)
{
Comms::SerialPort::send((Byte)torque);
return 1;
}
namespace Comms
{
//static p1 = gcnew System::IO::Ports::SerialPort();
int SerialPort::openPort()
{
bool check=0;
p1 = gcnew System::IO::Ports::SerialPort();
p1->BaudRate = 57600;
p1->PortName = "COM3";
if(p1->IsOpen)
return 0;
else {
p1->Open();
return 1;
}
}
int SerialPort::check()
{
array<String^>^ serialPorts = nullptr;
bool flag = true;
serialPorts = p1->GetPortNames();
for each(String^ port in serialPorts)
{
if(port=="COM3")
flag= true;
}
return flag;
}
void SerialPort::closePort()
{
p1->Close();
}
void SerialPort::send(Byte data)
{
array<unsigned char>^ buffer = gcnew array<Byte>(1);
buffer[0] = (char)data;
p1->Write(buffer,0,1);
}
double SerialPort::read()
{
double data;
data = p1->ReadByte();
return data;
}
}
header
#define PHANTOMADAPTER_API __declspec(dllexport)
#else
#define PHANTOMADAPTER_API __declspec(dllexport)
#endif
#using <mscorlib.dll>
#using <system.dll>
using namespace System;
using namespace System::IO::Ports;
using namespace System::Threading;
extern "C" {
PHANTOMADAPTER_API int ready();
PHANTOMADAPTER_API int open();
PHANTOMADAPTER_API int close();
PHANTOMADAPTER_API int angle(double& angle);
PHANTOMADAPTER_API int torque(double torque);
}
namespace Comms
{
public ref class SerialPort
{
private:
static System::IO::Ports::SerialPort^ p1;
public:
static int openPort();
static void closePort();
static double read();
static void send(Byte data);
static int check();
};
}
I am getting the following error when I call the angle DLL function or any function that requires the Comms namespace.
System.NullReferenceException: Object reference not set to an instance of an object.
at System.IO.Ports.SerialPort.get_IsOpen()
at System.IO.Ports.SerialPort.ReadByte()
at angle(Double* angle)
can someone please point me in the right direction, I feel as if the serialPort class can't be open from runtime library unless I import it somehow