The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Проблема с заполнением контейнера в C++, !*! siegerstein, 29-Ноя-07, 17:51  [смотреть все]
Приветствую всех!

Данная тема относиться к C++ но немножко будет нестадартна тем, что для ее расмотрения нужна звуковая система OSS ( http://developer.opensound.com )
Ближе к делу.

OSS - когда-то проприетарные, сейчас Open Source GPL v.2 звуковые драйвера для всех видов UNIX.
Избрал именно их - ибо единственные в своем роде которые пашут на разных UNIX.

Нужно заполнить контейнер  неякими данными.
Проблема в том, что если использовать
std::map<std::string, int> список создаеться нормально.
А вот при std::map<const char*, int> не хочет.

Мне нужно как раз char* и не std::string...
Пробывал заполнять другими данными - без проблем с char* и с std::string.
Какой-то полтергейст. Не понятно почему не хочет именно в моем случае:

Ниже выкладываю текст.
Компилил с использованием OSS v.4 и gcc 4.1.2

Проверял в GNU/Linux, должно работать также и в *BSD.
ВНИМАНИЕ: OSS v.4! OSS < v.4 не подойдет... Там совершенно другой API. Хотя все может быть..

Если нужна помощь в установке самых драйверов в GNU/Linux, FreeBSD - помогу.

/*
Using OSS v.4.0 (b071114/200711211324) GPL license. OSS API v.40003
ICH AC97 Mixer (AD1985)

GCC 4.1.2 GNU/Linux

g++ bug.cpp -o bug
./bug

Creating not correctly list with using std::map<const char*, int>
Only work with std::map<std::string, int>

Two part of this file (working and not working) are identicaly, with once defference:
Not working: std::map<const char*, int>
Working: std::map<std::string, int>

Author: Alex J. Ivasyuv // SIEGERSTEIN
Bug version under GPL, working under proprietary :)) // joke
*/

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sys/ioctl.h>
#include <fcntl.h>

#include "/usr/lib/oss/include/sys/soundcard.h"

int mixer_fd = -1;
    int mixer_dev = 0;
    int nrext = -1;
    
    oss_mixext ext;

int main() {

    if ((mixer_fd = open("/dev/mixer", O_RDWR)) == -1) {
        perror ("/dev/mixer");
        exit (-1);
}
    
    nrext = mixer_dev;
    if ( ioctl ( mixer_fd, SNDCTL_MIX_NREXT, &nrext ) == -1 ) { // nrext = 72
        perror ("SNDCTL_MIX_NREXT");
        return 1;
}
    
    if (ioctl(mixer_fd, SNDCTL_MIX_EXTINFO, &ext) == -1) {
        perror("SNDCTL_MIX_EXTINFO");
        return 1;
}
    
    /*******************************************************************************************/
    /*  NOT WORKING */
    std::map<const char*, int> NOT_AVAIBLE_MIX_DEV;
        
        for ( int i = 1; i < nrext; i++ ) {
            ext.dev = mixer_dev;
            ext.ctrl = i;
            ioctl(mixer_fd, SNDCTL_MIX_EXTINFO, &ext);
            if ( ( ext.type == MIXT_MONOSLIDER ) || ( ext.type == MIXT_STEREOSLIDER ) || (ext.type == MIXF_RECVOL ) ) {
                if ( ext.extname != NULL ) {

                    NOT_AVAIBLE_MIX_DEV[ext.extname] = i;
                    
}
}
}
        
        std::cout << std::endl << "******************************************" << std::endl;
        std::cout << "Starting NOT working method..." << std::endl << std::endl;
        for (std::map<const char*, int>::iterator it = NOT_AVAIBLE_MIX_DEV.begin(); it != NOT_AVAIBLE_MIX_DEV.end(); ++it) {
            std::cout << "it->first: " << it->first << std::endl;
            std::cout << "it->second: " << it->second << std::endl;
            std::cout << std::endl;
}
        std::cout << "End NOT working method." << std::endl;
        std::cout << "******************************************" << std::endl << std::endl;
        /****************************************************************************************/
        
        /*******************************************************************************************/
        /*  WORKING */
        std::map<std::string, int> NORM_AVAIBLE_MIX_DEV;
        
        for ( int i = 1; i < nrext; i++ ) {
            ext.dev = mixer_dev;
            ext.ctrl = i;
            ioctl(mixer_fd, SNDCTL_MIX_EXTINFO, &ext);
            if ( ( ext.type == MIXT_MONOSLIDER ) || ( ext.type == MIXT_STEREOSLIDER ) || (ext.type == MIXF_RECVOL ) ) {
                if ( ext.extname != NULL ) {

                    NORM_AVAIBLE_MIX_DEV[ext.extname] = i;
                    
}
}
}
        
        std::cout << "******************************************" << std::endl;
        std::cout << "Starting working method..." << std::endl << std::endl;
        for (std::map<std::string, int>::iterator it = NORM_AVAIBLE_MIX_DEV.begin(); it != NORM_AVAIBLE_MIX_DEV.end(); ++it) {
            std::cout << "it->first: " << it->first << std::endl;
            std::cout << "it->second: " << it->second << std::endl;
            std::cout << std::endl;
}
        std::cout << "End working method." << std::endl;
        std::cout << "******************************************" << std::endl << std::endl;
        /****************************************************************************************/
        
    return 0;
    
}

В итоге выходит такое:

$ ./bug

******************************************
Starting NOT working method...

it->first: vmix0-in
it->second: 34

End NOT working method.
******************************************

******************************************
Starting working method...

it->first: aux1
it->second: 20

it->first: cd
it->second: 15

it->first: center
it->second: 34

it->first: igain
it->second: 18

it->first: line
it->second: 9

it->first: mic
it->second: 12

it->first: mono
it->second: 26

it->first: pcm
it->second: 5

it->first: phone
it->second: 23

it->first: rear
it->second: 32

it->first: speaker
it->second: 7

it->first: video
it->second: 29

it->first: vol
it->second: 2

End working method.
******************************************

Кто-то может почему оно не работает? Может я что-то не то делаю?

Зарание спасибо за ответ.

  • Проблема с заполнением контейнера в C++, !*! elvenic, 18:55 , 29-Ноя-07 (1)
    • Проблема с заполнением контейнера в C++, !*! siegerstein, 20:51 , 29-Ноя-07 (2)
      Спасибо elvenic за ответ. Очень выручил.
      Даже в списках рассылки OSS не кто не ответил...

      > но могу предположить что значение указателя ext.extname каждый раз одно и то же

      Действительно это верно, поменял
      std::map<std::string, int> NORM_AVAIBLE_MIX_DEV
      на
      std::map<int, std::string> NORM_AVAIBLE_MIX_DEV
      и map сразу заполнился нужным количеством значений (но к сожалению не верными значениями ).

      > создается новый обьект std::string значение которого и используется как ключ мапа.

      В конечном итоге решил проблему вот так:

          std::map<const char*, int> NOT_AVAIBLE_MIX_DEV;
          std::map<std::string, int> tmpCont;
              
              for ( int i = 1; i < nrext; i++ ) {
                  ext.dev = mixer_dev;
                  ext.ctrl = i;
                  ioctl(mixer_fd, SNDCTL_MIX_EXTINFO, &ext);
                  if ( ( ext.type == MIXT_MONOSLIDER ) || ( ext.type == MIXT_STEREOSLIDER ) || (ext.type == MIXF_RECVOL ) ) {
                      if ( ext.extname != NULL ) {
                          tmpCont[ext.extname] = i;
                      }
                  }
              }
              
              for (std::map<std::string, int>::iterator it = tmpCont.begin(); it != tmpCont.end(); ++it) {
                  const char * tmpVal = it->first.c_str();
                  NOT_AVAIBLE_MIX_DEV[tmpVal] = it->second;
              }
      Решение банальное, но лутшего способа пока что не вижу...
      Сначала заполняем map тот что std::string а потом нормальные значения уже сново через цикл запихиваем уже во второй map но уже с const char*.

      Все равно до конца так и не понял почему не можно было сделать за один проход...
      P.S. Я в C++ новичек..

      • Проблема с заполнением контейнера в C++, !*! elvenic, 23:36 , 29-Ноя-07 (3)
        • Проблема с заполнением контейнера в C++, !*! siegerstein, 00:24 , 30-Ноя-07 (4)
          > А почему такое странное требование - получить в результате именно std::map<char *, int>?

          Все просто, не раз сталкивался с тем, что приходилось все время переводить потом с std::string в const char*.
          Вот к примеру мой случай:

                      QLabel *mixDevLabel = new QLabel;
                      mixDevLabel -> setText ( DEV_NAME );
                      
          Благо что DEV_NAME const char*, а то пришлось бы переводить. И таких случаев много.
          Заметил что многие API куда чаще используют const char* в замен std::string.
          О части из-за того что std::string нету в C?

          > Мап существует для того чтобы в него класть данные с ключами и потом находить положенные данные по этим ключам.

          У меня в мапе привязаное имя устройства к его идентификатору в системе, и оно не обезательно идет по порядку, то есть может быть так:
          vol => 2
          pcm => 4
          gain =>7

          > у меня есть сомнения не только по поводу std::map<char *, ...>, но и по поводу правомочности сохранения в мапе указателя который возвращает c_str().

          А что не так?
          Но как бы там небыло, у меня работает :))




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру