2016-01-28 7 views
2

Я пытаюсь воспроизвести аудиофайл .mod в исполняемом файле. Я использую сторонний BASSMOD .dll. Я могу заставить звуковой файл играть, когда я предоставляю полный путь к файлу, но я не могу заставить его играть, когда вы предоставляете относительный путь. Вот некоторые фрагменты.C++ char * относительный путь к файлу? (Qt)

main.cpp

#include <QCoreApplication> 
#include "bassmod.h" 

// define file location 
const char* file = "C:/Users/Downloads/test4/console/music.mod"; 

void startMusic() { 
    BASSMOD_Init(-1, 44100, 0); 
    BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS); 
    BASSMOD_MusicPlayEx(0,-1,TRUE); 
} 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    startMusic(); 
    return a.exec(); 
} 

bassmod.h (отношение сниппет)

BOOL BASSDEF(BASSMOD_MusicLoad)(BOOL mem, void* file, DWORD offset, DWORD length, DWORD flags); 

Функция Я беспокоит BASSMOD_MusicLoad. Поскольку этот проект стоит, файл .mod не будет работать. Однако, когда я пытаюсь изменить абсолютный путь файла .mod на относительный путь («music.mod»), файл не воспроизводится. Почему это? У меня есть файл .mod в том же каталоге, что и исполняемый файл, а также в каталоге, содержащем файл .pro, что, похоже, не было проблемой.

Кроме того, может быть, я пропустил что-то, связанное с тем, как файлы открываются в C++. Похоже, функция MusicLoadтребует, чтобы второй параметр имел тип void*. Я уверен, что здесь есть много разных вещей. В идеале я хотел бы иметь file хранить относительный путь к файлу .mod и заставить его играть так, поэтому мне не нужно жестко кодировать абсолютный путь. В идеальном мире я хотел бы предоставить file путь к файлу .mod в моем resource.qrc, но тогда мне придется использовать QFile, я считаю, что это не сработает, потому что мне нужен тип, который будет недействительным *.

Любая помощь для новичков будет оценена по достоинству.


EDIT 01: Спасибо всем за помощь! Я получил его на работу (по крайней мере, используя относительный путь к файлу). Есть два способа сделать это. Вот что я сделал и как я его протестировал:

Первый случай делает предположение, что BASSMOD (или любая внешняя dll, которую вы используете) не обрабатывает относительные пути.

const char* file = "C:/debug/music.mod"; // same dir as .exe 
QFileInfo info("music.mod"); 
QString path = info.absoluteFilePath(); 
const string& tmp = path.toStdString(); 
const char* raw = tmp.data(); 

Это те элементы, которые я поставил. Когда я запускаю BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);, он работает так, как ожидалось. Вот когда я жестко программирую полный абсолютный путь.

Когда я побежал BASSMOD_MusicLoad(FALSE,(void*)raw,0,0,BASS_MUSIC_RAMPS);, он не сработал. Поэтому я решил напечатать значения для всего, чтобы увидеть, где это Мессинг:

cout << "Qstring path: "; 
qDebug() << path; 
cout << "string& tmp: "; 
cout << tmp << endl; 
cout << "raw: "; 
cout << raw << endl; 
cout << "full char* file: "; 
cout << file; 
startMusic(); 

... возвращает это:

Qstring path: 
"C:/myApp/build-Debug/music.mod" 
string& tmp: 
C:/myApp/build-Debug/music.mod 
raw: 
C:/myApp/build-Debug/music.mod 
full char* file: 
C:/myApp/build-Debug/debug/music.mod 

Обратите внимание на разницу? Когда я жестко закодировал полный путь к файлу, я обнаружил, что (благодаря @FrankOsterfeld и @JasonC) текущий рабочий каталог на самом деле не был там, где были найдены файлы .exe (/ debug) или .pro. Это было фактически в том же каталоге, что и Makefile.

Так что я просто изменил его на это: QFileInfo info("./debug/x.m"); и он сработал.

Несмотря на то, что проблема была связана с тем, что я не знал, где находится текущий рабочий каталог, решения @Radek, @SaZ и @JasonC помогли найти другой способ решить эту проблему (плюс это показало мне, как получить рабочие каналы и конвертировать между типами). Это хорошая рекомендация для людей, которые хотели бы использовать QFileInfo для определения того, где вы на самом деле находитесь в файловой системе. Я бы использовал это решение, если бы я использовал DLL, хорошо не обрабатывал относительные пути. Однако ...

Я задавался вопросом, могу ли я применить одно и то же решение к моему исходному коду (без использования QFileInfo и типов конвертирования и т. Д.). Я предположил, что BASSMOD не обрабатывал относительные пути из коробки. Я был неправ. Я изменил переменную file на const char* file = "./debug/x.m"; Это сработало!

Спасибо за помощь, всем!

Однако, я все равно хотел бы, чтобы это работало с использованием music.mod из файла ресурсов Qt. Исходя из ответов, однако, похоже, что это возможно, если только сторонняя библиотека, которую вы используете, не поддерживает систему ресурсов Qt.

+0

Какой код ошибки возвращает BASSMOD_MusicLoad? –

+0

Чтобы получить это, я бы просто положил 'cout << BASSMOD_ErrorGetCode();' под строку 'BASSMOD_MusicLoad'?Когда я это делаю, он просто возвращает «2» в stdout. EDIT: nevermind. Я нашел код ошибки в файле заголовка. «2» - '#define BASS_ERROR_FILEOPEN // не могу открыть файл' – orbit

+0

Так что он явно не может найти файл. Я предполагаю, что это имеет какое-то отношение к тому, как BASSMOD читает файл. Так как это скомпилированная .dll, к сожалению, это немного черный ящик. – orbit

ответ

4

У меня есть .mod файл в том же каталоге, что и исполняемый файл.

В Qt Creator начальный рабочий каталог по умолчанию является каталог, файл .pro находится, а не каталог, который .exe заканчивается в.

Либо поместить файл в этом каталоге (один вероятно, все исходные файлы и т. д., если вы использовали типичную настройку), или измените каталог запуска в каталог, в котором находится файл .exe (в области «Параметры запуска»).

Хотя, исходя из вашего нового комментария ниже, я думаю, проблема глубже, чем эта ... Я не могу сказать вам, почему BASS не любит относительные имена файлов, но вы можете преобразовать относительный путь в абсолютный перед тем, как передать его в BASS. Есть много способов сделать это; используя API в Qt вы можете:

#include <QFileInfo> 

... 
const char* file = "music.mod"; // Your relative path. 
... 

BASSMOD_MusicLoad(..., 
        (void*)QFileInfo(file).absoluteFilePath().toAscii().data(), 
        ...); 

В идеальном мире, я хотел бы предоставить файл с путем к файлу .mod в моем resources.qrc

Вы не будете что загрузка ресурсов из файлов .qrc - это вещь Qt, а BASS, по-видимому, не использует Qt внутренне (например, вы не можете открыть ресурс с помощью fopen) и не понимаете, как загружать ресурсы, встроенные Qt. Я не знаком с BASS, но беглый взгляд на this documentation показывает, что он также способен воспроизводить данные из буфера в памяти. Таким образом, одним из способов было бы использовать Qt для загрузки ресурса в доступную память и вместо этого передать этот буфер.

+0

Забыл упомянуть, что я повесил файл везде, где мог бы просто посмотреть, не проблема. Еще ничего. Даже когда я помещаю файл в тот же каталог, что и файл .pro. Тем не менее, это хороший совет. – orbit

+0

Я могу заглянуть в буфер памяти. Единственная проблема заключается в том, что программа попадает на антивирус, когда я это делаю по какой-то причине, чего я определенно не хочу иметь. – orbit

+0

@orbit См. Редактирование, я предполагаю, что преобразование его в абсолютный путь может работать, хотя на самом деле оно не затрагивает причины его возникновения в первую очередь. –

-1

В идеальном мире я хотел бы предоставить файл с файлом .mod в моем resource.qrc, но тогда мне придется использовать QFile, я считаю, что это не сработает, потому что я нужен тип, который будет недействительным *.

Почему вы верите в существование? Прочтите Qt Doc. Это будет работать. Не используйте класс QFile, но QFileInfo.

QFileInfo info(:/resourcePrefix/name); 
QString path = info.absoluteFilePath(); 
void* rawPtr = (void*)path.toStdString().c_str(); 
+1

'void * rawPtr = (void *) path.toStdString(). C_str();' - этот указатель будет недопустим в следующей строке кода, потому что 'path.toStdString()' является значением rvalue. Не делай этого. –

+2

Следующая ошибка: вы не можете работать с пути qt resource, например ':/resourcePrefix/name', вне библиотеки Qt, потому что вы не уверены, что BASS поддерживает систему ресурсов Qt. Я верю, что нет. –

+0

@SaZ к первому комментарию: он будет работать, пока код не достигнет конца блока, чем строка освобождается из памяти (я согласен, что toStdString() создает копию) и становится недействительным. Пока этот пользователь не загрузит данные с BASSMOD_MusicLoad. – Radek

 Смежные вопросы

  • Нет связанных вопросов^_^