wxWidgets - wybór pliku do odtworzenia

0

Nie dawno założyłem podobny temat lecz niestety nie dostałem odpowiedzi, być może zbyt niedokładnie opowiedziałem mój problem. Wybaczcie za drugi temat, ale postaram się tu to lepiej opisać.

Na samym początku proszę o cierpliwość, wiem, że jest trochę tego tekstu, ale starałem się wszystko dostatecznie jasno wytłumaczyć. Problem sam w sobie być może okazać się prosty jeśli przeanalizujecie moją sytuację, bo nie jestem zaawansowanym programistą, uczę się tego od października i to jako dodatkowy przedmiot jedynie.

W programie moim użyłem biblioteki wxWidgets - powszechnie znana do robienia aplikacji okienkowych i malutkiej biblioteki "audiere" która to zajmuje się dźwiękiem.

Otóż napisałem taki mini sampler który po naciśnięciu klawiszy odgrywa przypisane im dźwięki. Znajdują się one na dysku komputera oczywiście. Dźwięki przypisałem manualnie w kodzie i wprowadziłem ścieżkę do obiektu biblioteki audiere:

AudioDevicePtr audiodevice( OpenDevice() ); // tu chodzi chyba o dostęp do karty
/* dźwiękowej, każdy dźwięk  przy          "wywołaniu" w kodzie z tego korzysta (audiodevice - nazwa którą sami nadajemy)*/

sound[ 'R' ] = OpenSoundEffect( audiodevice, "C:/Users/samsung/Desktop/Synth Effects/FX-RISEUP.wav", audiere::MULTIPLE );
 

Objaśnienie: sound to mapa która wiąże klawisz z dźwiękiem. Obydwie linijki znajdują się w konstruktorze klasy która dzidziczy z wxFrame: public . Klasa tą utworzyłem, żeby posługując się biblioteką okienkową, tworzyć w niej okno, przyciski, i inne rzeczy wyświetlane w okienku.

Chciałem, żeby w programie użytkownik sam mógł wybrać jaki plik przypisze do klawisza, w tym celu umieściłem wxFileDialog (eksplorator do wyboru plików z dysku) i połączyłem jego naciśnięcie z taką funkcją składową klasy bito_blaster:

void bito_blaster::WybierzPlik( wxCommandEvent & event ) {
   
    okno_wyboru->ShowModal();
    string path = okno_wyboru->GetPath();
    string klawisze = "ASDFHJKLXCBN";
    wxString path2 = MakePath( path );
    if( lista_klawiszy->GetSelection() != - 1 ) {
        sound[ klawisze[ lista_klawiszy->GetSelection() ] ] = OpenSoundEffect( audiodevice, path2,
        audiere::MULTIPLE );
       
        tekst->SetLabel( "Wybrales klawisz: " + num2str( lista_klawiszy->GetSelection() ) + "\n sciezka: " + path2 );
    }
    else { tekst->SetLabel( "WYBIERZ KLAWISZ DO PRZYPISANIA" ); }
}

//tekst - pomocniczy tekst do sprawdzania czy wszystko ok
//lista_klawiszy - wxListBox wybierasz klawisz do ktorego bedzie przypisane
okno_wyboru- wxFileDialog - wybierasz plik, funkcja getPath zwraca dobrą ścieżkę, sprawdzałem
(MakePath() zwraca string i jedynie zamienia \ na / w ścieżce, bo takie ukośniki są wymagane)

Niestety jak wywołuje w programie funkcje WybierzPlik, to następnie po naciśnięciu klawisza do którego przypisałem dźwięk program się zawiesza. Co mogę robić źle? To jakiś problem z pamięcią, w złym miejscu konstruuje jakiś z obiektów klasy audiere do odtwarzania dźwięku? Co może być nie tak, proszę o pomoc.

0

A debugera użyć nie możesz? Za mało kodu podałeś, bo w tym co jest nie widać niczego, co mogłoby powodować błąd.

p.s. tak powinno być:

if(okno_wyboru->ShowModal() == wxID_OK)
{
    string path = okno_wyboru->GetPath();
    // ... i cała reszta kodu, która powinna być wykonana po wybraniu pliku

}

okno_wyboru zrobiłbym lokalnym obiektem...

0

Problem jest w czym innym jednak, niepotrzebnie się tyle napisałem :D

problemem wydaje się być przekazanie ścieżki do:

sound[ 'R' ] = OpenSoundEffect( audiodevice, "C:/Users/samsung/Desktop/Synth Effects/FX-RISEUP.wav", audiere::MULTIPLE );

to jest dla mnie niezrozumiałe...

OpenSoundEffect w konstruktorze życzy sobie jako drugi argument (po audiodevice) wprowadzenie SampleSourcePtr. Jeśli w ty miejscu tak jak wyżej napiszę stringa, to działa ( czy to aby na pewno string) nie wiem, czy następuje wtedy jakaś konwersja czy co, ale radzi sobie z odczytaniem jesli w konstruktorze podam mu ścieżkę jak powyżej.

Funkcja pobierania ścieżki okno_wyboru->GetPath(); działa tak, że ścieżka którą pobiera ma ukośniki w drugą stronę niż sobie to audiere życzy. Tak więc utworzyłem funkcje MakePath która zamienia te wykrzykniki i zwraca ścieżkę z zmienionymi \ na / .

Funkcja Make Path wygląda tak:

string bito_blaster::MakePath(string oldPath){
	//string newPath ;
	
	char a = 92; // backslash

	for(int i=0; i < oldPath.length(); i++){
		
		if( oldPath[i] == a)
		{
			oldPath[i] ='/';
		}
	}
	return oldPath;
}

Jeśli natomiast wpiszę:

 
string path = okno_wyboru->GetPath();
OpenSoundEffect(audiodevice, MakePath(path), audiere::MULTIPLE);

to podkreśla mi OpenSoundEffect i jest napisane: "No overload function matches the argument list".
Jeśli nastawię, aby MakePath zwracało wxString zamiast stringa, to i tak nie działa, ale nie podkreśla tego OpenSoundEffect - kompulije się, ale po naciśnięciu klawisza do którego przypisałem to, wyskakuje błąd, taki jakby nie znalazło pliku(cos z pamięcią (?)), program się zawiesza.

Domyślam się, że muszę jakoś zamienić stringową ścieżkę na obiekt klasy SampleSourcePtr, jak to zrobić?
Nie wiem jak poruszać się w plikach bibliotekowych... Muszę szukać konstruktora SampleSourcePtr? w pliku nagłówkowym audiere.h nie umiałem tego znaleźć.

Znalazłem jedynie takie fragmenty:

 
typedef RefPtr<SampleSource> SampleSourcePtr;

 const SampleSourcePtr& source)
  {
    return hidden::AdrCreateLoopPointSource(source.get());
  }

 const SampleSourcePtr& source,
    SoundEffectType type)
  {
    return hidden::AdrOpenSoundEffect(device.get(), source.get(), type);
  }

const SampleSourcePtr& source,
    bool streaming = false)
  {
    return hidden::AdrOpenSound(device.get(), source.get(), streaming);
  }

inline SampleBuffer* CreateSampleBuffer(const SampleSourcePtr& source) {
    return hidden::AdrCreateSampleBufferFromSource(source.get());
  }

0

Jeśli natomiast wpiszę: (...) to podkreśla mi OpenSoundEffect i jest napisane: "No overload function matches the argument list".

Sprawa prosta: OpenSoundEffect oczekuje wskaźnika const char*, dostaje std::stringa, który nie ma operatora konwersji na wspomniany wskaźnik (wxString, jeśli dobrze pamiętam, ma taki). Dlatego też kompilator nie może znaleźć odpowiedniej wersji funkcji ze stringiem w parametrze.

Przerób MakePath na wersję z wxString, i wtedy spróbuj tak:

OpenSoundEffect(audiodevice, 
		MakePath( okno_wyboru->GetPath() ).mb_str( wxConvLocal ), 
		audiere::MULTIPLE);
   char a = 92; // backslash

Magiczne numery to zuo! Nie można tak:

char a = '\\'; 

?

0

Problem prawdopodobnie leży w tej linijce:

sound[ klawisze[ lista_klawiszy->GetSelection() ] ] = OpenSoundEffect( audiodevice, path2,
        audiere::MULTIPLE );
  1. Rozbij to funkcjonalnie tak żeby było widać co robisz
wybor = lista_klawiszy->GetSelection();

klawisz = klawisze[ lista_klawiszy->GetSelection() ];

dzwiek = OpenSoundEffect( audiodevice, path2,
        audiere::MULTIPLE );

sound[ klawisz ] = dzwiek;

(oczywiście musisz zadeklarować wcześniej wszystkie te zmienne)

  1. następnie pod debuggerem przyjrzyj się wartościom ww zmiennych w trakcie działania programu

  2. jeśli wszystkie będą wyglądały dobrze, zakomentuj wybrane ww linijki kodu zastępując je stałymi (tak jak to zrobiłeś ze ścieżką). Po tym już są małe szanse że nie znajdziesz przyczyny.

  3. Gdybyś jednak nadal miał wątpliwość, pozostaje przeczytanie manuala do wywoływanych funkcji ;-)

0

Dzieki mojemu laborantowi Panu Wiciowskiemu któremu bardzo dziękuje udało mi się dojść trochę dalej.

Rozgryźliśmy tą konwersje że trzeba zamienić ścieżkę na const char i zastosowaliśmy coś takiego:

string Path = makePath("C:\\Users\\samsung\\Desktop\\sample\\pad samples\\ruben_pad_1_c4.wav");
sound['E'] =  OpenSoundEffect( audiodevice,Path.c_str(),
				audiere::MULTIPLE);
 

W konstruktorze działa, pięknie przypisuje ten dźwięk, ale w funkcji WybierzPlik, NIE DZIAŁA, nawet jak wpiszemy dokładnie to samo!!!

Żeby do bólu uprościć sprawe wpisałem w funkcji wybierzPlik taki prosty kod:

 void bito_blaster::WybierzPlik(wxCommandEvent& event){

	string Path = makePath("C:\\Users\\samsung\\Desktop\\sample\\pad samples\\ruben_pad_1_c4.wav");
	
	sound['E'] =  OpenSoundEffect( audiodevice, Path.c_str(), audiere::MULTIPLE);

}

cała reszta zakomentowana a ...

rezultat ciągle ten sam!!! nie rozumiem, wpisuje dokłądnie to samo w konstruktorze mojego okna i wszystko działa pięknie, kopiuje to pare linijek w dół do funkcji składowej mojej klasy połączonej z przyciskiem, i dupa. Po uruchomieniu programu i naciśnięciu E dźwięk się odtwarza, bo został przypisany w konstruktorze, ale jak naciskam WybierzPrzycisk, to zaraz przestaje grać. A ponowne uruchomienie go skutkuje przerwaniem programu (zawieszenie) a oto piękny nic niemówiący mi komunikat:P

Unhandled exception at 0x773f15de in ProjektJPWP.exe: 0xC0000005: Access violation reading location 0x00000000.

Proszę o pomoc i serdecznie dziękuje ;)

0

Jak podłączasz WybierzPlik do zdarzenia? Makrem czy metodą Connect? Pokaż call stack z momentu wystąpienia błędu.

0

Connect( btCHOOSEFILE, wxEVT_COMMAND_BUTTON_CLICKED , wxCommandEventHandler(bito_blaster::WybierzPlik));

0

Metoda wywołana na rzecz obiektu klasy bito_blaster, tak?

0

Nie rozumiem, jak "na rzecz obiektu" ? w Connect jest idprzycisku, makro czy jakkolwiek sie do zwie, i w EventHandler jest podłączenie do funkcji WybierzPlik która to jest zdefiniowana w klasie bito_blaster.

0

Gdzie wywołujesz metodę Connect?

0

W konstruktorze klasy bito_blaster rzecz jasna:P

0

Pokaż wspomniany call stack. Czym jest sound?

0

sound jest mapą, jako pierwszy argument przyjmuje nazwę klawisza , jako drugi obiekt audiere :

map<char, SoundEffectPtr > sound;

oto CallStack:

ntdll.dll!773f15de() 	
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]	
ntdll.dll!773f15de() 	
ntdll.dll!773e014e() 	
ProjektJPWP.exe!wxAppConsoleBase::HandleEvent(wxEvtHandler * handler, void (wxEvent &)* func, wxEvent & event)  Line 595 + 0xf bytes	C++
ProjektJPWP.exe!wxAppConsoleBase::CallEventHandler(wxEvtHandler * handler, wxEventFunctor & functor, wxEvent & event)  Line 607 + 0x22 bytes	C++
ProjektJPWP.exe!wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase & entry, wxEvtHandler * handler, wxEvent & event)  Line 1331 + 0x29 bytes	C++
ProjektJPWP.exe!wxEvtHandler::SearchDynamicEventTable(wxEvent & event)  Line 1673 + 0x11 bytes	C++
ProjektJPWP.exe!wxEvtHandler::TryHereOnly(wxEvent & event)  Line 1518 + 0x15 bytes	C++
ProjektJPWP.exe!wxEvtHandler::TryBeforeAndHere(wxEvent & event)  Line 3343 + 0x2d bytes	C++
ProjektJPWP.exe!wxEvtHandler::ProcessEventLocally(wxEvent & event)  Line 1455 + 0xc bytes	C++
ProjektJPWP.exe!wxEvtHandler::ProcessEvent(wxEvent & event)  Line 1428 + 0xc bytes	C++
ProjektJPWP.exe!wxEvtHandler::SafelyProcessEvent(wxEvent & event)  Line 1535 + 0x13 bytes	C++
ProjektJPWP.exe!wxWindowBase::HandleWindowEvent(wxEvent & event)  Line 1457	C++
ProjektJPWP.exe!wxWindow::HandleKeyDown(unsigned int wParam, long lParam)  Line 5779 + 0xc bytes	C++
ProjektJPWP.exe!wxWindow::MSWHandleMessage(long * result, unsigned int message, unsigned int wParam, long lParam)  Line 3096 + 0x11 bytes	C++
ProjektJPWP.exe!wxWindow::MSWWindowProc(unsigned int message, unsigned int wParam, long lParam)  Line 3613 + 0x22 bytes	C++
ProjektJPWP.exe!wxAnyButton::MSWWindowProc(unsigned int nMsg, unsigned int wParam, long lParam)  Line 638	C++
ProjektJPWP.exe!wxButton::MSWWindowProc(unsigned int nMsg, unsigned int wParam, long lParam)  Line 438	C++
ProjektJPWP.exe!wxWndProc(HWND__ * hWnd, unsigned int message, unsigned int wParam, long lParam)  Line 2711 + 0x1e bytes	C++
user32.dll!764a62fa() 	
user32.dll!764a6d3a() 	
user32.dll!764a6ce9() 	
user32.dll!764a77c4() 	
user32.dll!764a788a() 	
user32.dll!764cc81f() 	
ProjektJPWP.exe!wxWindow::MSWProcessMessage(tagMSG * pMsg)  Line 2495 + 0x15 bytes	C++
ProjektJPWP.exe!wxGUIEventLoop::PreProcessMessage(tagMSG * msg)  Line 251 + 0x16 bytes	C++
ProjektJPWP.exe!wxGUIEventLoop::ProcessMessage(tagMSG * msg)  Line 269 + 0x13 bytes	C++
ProjektJPWP.exe!wxGUIEventLoop::Dispatch()  Line 333 + 0x13 bytes	C++
ProjektJPWP.exe!wxEventLoopManual::ProcessEvents()  Line 109 + 0xf bytes	C++
ProjektJPWP.exe!wxEventLoopManual::Run()  Line 159 + 0x8 bytes	C++
ProjektJPWP.exe!wxAppConsoleBase::MainLoop()  Line 318 + 0x27 bytes	C++
ProjektJPWP.exe!wxAppConsoleBase::OnRun()  Line 259 + 0x12 bytes	C++
ProjektJPWP.exe!wxAppBase::OnRun()  Line 285	C++
ProjektJPWP.exe!wxEntryReal(int & argc, wchar_t * * argv)  Line 472 + 0x1d bytes	C++
ProjektJPWP.exe!wxEntry(int & argc, wchar_t * * argv)  Line 189 + 0xd bytes	C++
ProjektJPWP.exe!wxEntry(HINSTANCE__ * hInstance, HINSTANCE__ * __formal, HINSTANCE__ * __formal, int nCmdShow)  Line 414 + 0x10 bytes	C++

ProjektJPWP.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow) Line 13 + 0x31 bytes C++
ProjektJPWP.exe!__tmainCRTStartup() Line 547 + 0x2c bytes C
ProjektJPWP.exe!WinMainCRTStartup() Line 371 C
kernel32.dll!753033aa()
ntdll.dll!77409ef2()
ntdll.dll!77409ec5()

0

Pomoże to coś?

0

To jest zrzut z momentu wystąpienia błędu, tak? Dziwne, wygląda jakby WybierzPlik nie była wywoływana. Nie ma jej na liście, a powinna być, jeśli założyć, że występuje w niej błąd. Jedyne co mi teraz przychodzi do głowy to to, że obiekt klasy bito_blaster, na rzecz którego wywoływany jest handler, po prostu nie istnieje. Chyba że coś pominęliśmy...

Co do sound. Jest to składnik klasy bito_blaster?

0

Tak Sound jest zdeklarowany jako private w bito_blaster. Funkcja WybierzPlik musi być wykonywana, bo wcześniej umieściłem tam polecenie, żeby zmieniło mi Label pola tekstowego tekst->SetLabel(ścieżka którą pobierze) i zmieniało się to pole tekstowe elegancko.

CallStack był pusty, bo (tak mi się wydaje) nie funkcja WybierzPlik zawiesza program, tylko to co się w niej dzieje - to przypisanie. A dokładniej odtworzenie tego przypisania potem.

Jak naciskam WybierzPrzycisk, nic się nie dzieje, jedynie jesli potem nacisnę klawisz do którego przypisałem w funkcji WybierzPrzycisk jakiś dźwięk (odpowiada to odtworzeniu dźwięku od tego klawisza) to wówczas CallStack się zapełnia.

Dodam jeszcze, że przed uruchomieniem f. WybierzPlik dźwięk da się odtworzyć naciskając E (bo działa to przypisanie z konstruktora), ale po uruchomieniu tej funkcji już nie. Tak jakby nie dało się z nieznanego powodu ustawić ścieżki do dźwięku w tej funkcji, natomiast w konstruktorze się da...

0

Sypnie ktoś jeszcze jakimś pomysłem, tropem? Ja już sam nie mam pojęcia o co może chodzić mu, czemu nie wykonuje tych samych linijek kodu tak samo jak w konstruktorze, tylko jakiś błąd wprowadza jak chcę odtworzyć dźwięk :(

0

A to żeśmy się nie zrozumieli. Myślałem, że błąd (w sensie access violation...) wyskakuje w WybierzPlik. Dobra, nieważne. Swoją drogą w call stack nie widzę metody obsługującej naciśnięty klawisz. Gdzie ona jest?

0

Ja też jej nie widzę tam co jest dziwne. w Call Stack widać jedynie jakieś: wxWindow::HandleKeyDown

moja metoda którą sobie utworzyłem do obsługiwania naciśnięcia klawisza to:
jest dosc skomplikowana, i myslalem ze moze cos w niej jest źle jak już wszystkie pomysły wykorzystałem, ale zakomentowałem wszystko i zmieniłem jej treść na zwykłe:

sound[event.GetUnicodeKey()]->setVolume(1);
sound[event.GetUnicodeKey()]->play();

i też nie działało, te warunki dałem tam po prostu, żeby nie próbował program zagrać dźwięku jeśli przez przypadek naciśnie się klawisz do którego nie ma nic przypisane - taki który nie należy do stringu "klawisze" (żeby się nie zawieszał wtedy)

void bito_blaster::onKeyDown(wxKeyEvent& event)
{	
	string klawisze = "ASDFHJKLCVBNERYU";


	if ( event.ShiftDown() == false) {
		if(event.GetUnicodeKey() == 'M'){sound[event.GetUnicodeKey()]->setVolume(0.3);
		sound[event.GetUnicodeKey()]->play();}
		else if(event.GetUnicodeKey() == 'B' )
		{
			sound[event.GetUnicodeKey()]->setVolume(0.3);
			sound[event.GetUnicodeKey()]->play();
		}
		else if( klawisze.find(event.GetUnicodeKey()) < klawisze.length()){ 
			sound[event.GetUnicodeKey()]->setVolume(1);
			sound[event.GetUnicodeKey()]->play();
			tekst->SetLabel("znaleziono klawisz" + event.GetUnicodeKey ());
		} ;
	}
	else {
		
		if(klawisze.find(event.GetUnicodeKey()) < klawisze.length() )
			
			for (int i = 0 ; i <4; i++){
				//sound[event.GetUnicodeKey()]->setVolume(0.1);
				sound[event.GetUnicodeKey()]->play();
				czekaj(0.05);
			}
	}
}
 

opracowanie tej metody znalazłem na jakiejś zagranicznej stronie, dodatkowo mogę powiedzieć, że żeby ją podłączyć, w konstruktorze klasy bito_blaster dopisałem taką linijke (tak było w tym tutorialu):

 
this->connectKeyDownEvent(this);

natomiast connectKeyDown zdefiniowałem tak (również wg. tutorialu):

 
void bito_blaster::connectKeyDownEvent(wxWindow* pclComponent)
{
  if(pclComponent)
  {
    pclComponent->Connect(wxID_ANY,
                          wxEVT_KEY_DOWN,
                          wxKeyEventHandler(bito_blaster::onKeyDown),
                          (wxObject*) NULL,
                          this);
 
    wxWindowListNode* pclNode = pclComponent->GetChildren().GetFirst();
    while(pclNode)
    {
      wxWindow* pclChild = pclNode->GetData();
      this->connectKeyDownEvent(pclChild);
     
      pclNode = pclNode->GetNext();
    }
  }
}

nie wiem czy to ma znaczenie do tego co my robimy, ale być może wy zrozumiecie z tego więcej niż ja.
Ja byłem po prostu zadowolony, że sposób z tego angielskiego poradnika działa(ł).

0

w Call Stack widać jedynie jakieś: wxWindow::HandleKeyDown

To akurat jest OK, bardziej zastanawia mnie brak wywołania onKeyDown powyżej wxAppConsoleBase::HandleEvent. HandleEvent niewiele robi, wywołuje metodę odpowiedzialną za obsługę zdarzenia. Zatem jedyne co może wywołać w niej wyjątek, to nieprawidłowy wskaźnik na metodę obsługującą zdarzenie. Dlaczego tak się dzieje, nie wiem.

Pokaż całą klasę (jak jest duża, użyj pastebin).

Ja byłem po prostu zadowolony, że sposób z tego angielskiego poradnika działa(ł)

connectKeyDownEvent wygląda OK. Podłącza obsługę wxEVT_KEY_DOWN do obiektu klasy bito_blaster (this) i wszystkich jego okien/kontrolek potomnych.

0
nikhatlak napisał(a):

Unhandled exception at 0x773f15de in ProjektJPWP.exe: 0xC0000005: Access violation reading location 0x00000000.

Ten błąd oznacza że czytasz wartość wskazywaną przez adres NULL.
Może to być np. wywoływanie metody do obiektu który jest podany jako NULL.

Bez kodu całości będzie trudno, może źle podłączasz event, może źle wskazujesz sound... trudno powiedzieć.

0

Już miałem wklejać cały kod, ale problem, tymczasowo rozwiązałem sam.
Głupie audiere:P
Wczoraj późnym wieczorkiem postanowiłem trochę posprzątać kod i żeby było bardziej przejrzyście, zamiast przypisywać w konstruktorze klawiszom z tablicy sound dźwięki (obiekty audiere) to wrzuciłem to przypisanie do nowo stworzonej funkcji składowej bito_blaster. Co się okazało, też nie chciało ich czytać - identyczny błąd jak przedtem. Zastanowiłem się WTF?

i wpadłem na pomysł, żeby dodać do tej funkcji:
AudioDevicePtr audiodevice(OpenDevice());
czyli linijke która była w konstruktorze.

i działa.

Może mi to ktoś wytłumaczyć co sie działo? W pliku nagłówkowym klasy bito_blaster dodałem zmienną private:
AudioDevicePtr audiodevice;

następnie w konstruktorze ją zdefiniowałem:
AudioDevicePtr audiodevice(OpenDevice());

i w funkcjach składowych tak jakby nie istniała... (musi być tam jeszcze raz wpisana linijka AudioDevicePtr audiodevice(OpenDevice()); żeby zadziałało)

Próbowałem potem używać this i też nie działa ta linijka:

sound['E'] = OpenSoundEffect(this->audiodevice,Path.c_str(), audiere::MULTIPLE);

o co chodzi?

0

Chodzi o to, żebyś poczytał sobie o zmiennych i regułach zasięgu.

AudioDevicePtr audiodevice(OpenDevice());

Ta definicja zmiennej audiodevice przysłania składową bito_blaster::audiodevice, dlatego to, co do niej przypisałeś w konstruktorze, ma zasięg lokalny, poza konstruktorem nie istnieje.

Wystarczy takie przypisanie:

audiodevice = OpenDevice();
0

Pokazywałem wam zaraz na początku tą linijkę. Także można to było wcześniej rozpoznać.
Oczywiście mój błąd, wchodzę dopiero w świat bibliotek i wcześniej nie rozumiałem tej konstrukcji. Z symfonii standard C++ pamiętam o zasięgu zmiennych, lecz tutaj nie miałem pojęcia że nastąpi przysłonięcie. Myślałem, że to nie jest zwykła funkcja, tylko jakaś bardziej skomplikowana komenda o podłożu sięgającym niżej niż zwykłe funkcje C++ - jakieś dostanie się do karty dźwiękowej, czy coś.

Tak czy inaczej wielkie dzięki i dzięki wielkie. Bardzo mi to pomogło, myślę, że projekt na zajęcia wypali dobrze.

0

Pokazywałem wam zaraz na początku tą linijkę. Także można to było wcześniej rozpoznać.

Jedna linijka bez szerszego kontekstu niewiele mówi. Jak byś dał od razu kod klasy (tylko najważniejsze z punktu widzenia problemu metody), to błąd zostałby od razu wychwycony. A tak trzeba było się domyślać i zakładać, że pewne podstawowe rzeczy robisz poprawnie.

Na przyszłość: krótko i zwięźle opisuj problem, i dawaj więcej kodu.

Oczywiście mój błąd, wchodzę dopiero w świat bibliotek i wcześniej nie rozumiałem tej konstrukcji.

To nie ma związku z bibliotekami. Ta konstrukcja jest powszechna i oznacza definicje obiektu/zmiennej audiodevice z przekazaniem parametru do konstruktora. To można(by) zapisać tak:

AudioDevicePtr audiodevice = OpenDevice();

1 użytkowników online, w tym zalogowanych: 0, gości: 1