Rodio的Sink类型在结构体内使用时为何无法播放?

huangapple go评论63阅读模式
英文:

Why do Rodio's Sink types fail to play when used inside of a struct?

问题

I've translated the code portion as you requested. Here's the translated code:

use rodio::{OutputStream, Sink, Decoder};
use std::fs::File;
use std::io::{BufReader};

pub struct MusicStruct {
    sink: Sink
}

fn main() {
    // this will not play (using my struct type)
    let mut music = MusicStruct::new();
    let (_stream, stream_handle) = OutputStream::try_default().unwrap();
    let my_sink = Sink::try_new(&stream_handle).unwrap();
    // will sit here and hang forever (I guess because of how sleep_until_end() is written..)
    MusicStruct::test_play(music);

    // this does play (doing it how the docs suggest)
    let (_stream, stream_handle) = OutputStream::try_default().unwrap();
    let sink = Sink::try_new(&stream_handle).unwrap();
    sink.append(read_file_from_beginning("my_mp3.mp3".to_string()));
    sink.play();
    sink.sleep_until_end()
}

// makes a Decoder<BufReader<File>> from String
fn read_file_from_beginning(file: String) -> Decoder<BufReader<File>> {
    let reader = BufReader::new(File::open(file).unwrap());
    let decoder = Decoder::new(reader).unwrap();
    decoder
}

impl MusicStruct {
    // creates a Decoder<BufReader<File>> and appends it to the sink in our struct and plays it
    pub fn test_play(our_sink: MusicStruct) {
        let file = read_file_from_beginning("my_mp3.mp3".to_string());
        our_sink.sink.append(file);
        our_sink.sink.play();
        our_sink.sink.sleep_until_end()
    }

    pub fn new() -> MusicStruct {
        let (_stream, stream_handle) = OutputStream::try_default().unwrap();
        MusicStruct {
            sink: Sink::try_new(&stream_handle).unwrap()
        }
    }
}

Please note that I've removed the HTML escape codes (&amp; and &quot;) as they are not necessary in Rust code. If you have any further questions or need assistance with this code, feel free to ask.

英文:

Been trying to create a struct to do some music operations and I found that if you have a struct with a rodio::sink as a field, it will not play music.

Here is my code:


use rodio::{OutputStream, Source, Sink, Decoder};
use std::fs::File;
use std::io::{BufReader, Seek, SeekFrom};

pub struct MusicStruct {
    sink: Sink
}

fn main() {
    // this will not play (using my struct type)
    let mut music = MusicStruct::new();
    let (_stream, stream_handle) = OutputStream::try_default().unwrap();
    let my_sink = Sink::try_new(&amp;stream_handle).unwrap();
    // will sit here and hang forever (i guess bcs of how the sleep_until_end() is written..)
    MusicStruct::test_play(music);

    // this does play (doing it how the docs suggest)
    let (_stream, stream_handle) = OutputStream::try_default().unwrap();
    let sink = Sink::try_new(&amp;stream_handle).unwrap();
    sink.append(read_file_from_beginning(&quot;my_mp3.mp3&quot;.to_string()));
    sink.play();
    sink.sleep_until_end()
}


// makes a Decoder&lt;BufReader&lt;File&gt;&gt; from String
fn read_file_from_beginning(file: String) -&gt; Decoder&lt;BufReader&lt;File&gt;&gt; {
    let reader = BufReader::new(File::open(file).unwrap());
    let decoder = Decoder::new(reader).unwrap();
    decoder

}

impl MusicStruct {
    // creates a Decoder&lt;BufReader&lt;File&gt;&gt; and appends it to the sink in our struct and plays it
    pub fn test_play(our_sink: MusicStruct) {
        let file = read_file_from_beginning(&quot;my_mp3.mp3&quot;.to_string());
        our_sink.sink.append(file);
        our_sink.sink.play();
        our_sink.sink.sleep_until_end()
    }


   pub fn new() -&gt; MusicStruct {
        let (_stream, stream_handle) = OutputStream::try_default().unwrap();
        MusicStruct {
            sink: Sink::try_new(&amp;stream_handle).unwrap()
        }
    }
}

I didn't see anything mention this in the docs / other resources. Am I doing something wrong here? I looked into the source code but didn't really see much in sink that would cause this behavior (albeit I'm not great at rust, so..)

Would appreciate any thoughts or answers !

答案1

得分: 2

需要让 OutputStream 的生命周期与 sink 一样长。简单的修复方法是将其添加到结构体中:

pub struct MusicStruct {
    sink: Sink,
    stream: OutputStream
}

并且修改 new 函数以包括它:

pub fn new() -> MusicStruct {
    let (stream, stream_handle) = OutputStream::try_default().unwrap();
    MusicStruct {
        sink: Sink::try_new(&stream_handle).unwrap(),
        stream
    }

编辑:
更好的方法是这样做(并且更容易与线程一起使用):

let (stream, stream_handle) = OutputStream::try_default().unwrap();
std::mem::forget(stream);

这在 bevy 游戏引擎中官方使用。只要您不构建多个这样的结构就可以。

英文:

Need to have the OutputStream live for as long as the sink. Simple fix was adding it to the struct:

pub struct MusicStruct {
    sink: Sink,
    stream: OutputStream
}

and changing the new function to include it:

   pub fn new() -&gt; MusicStruct {
        let (stream, stream_handle) = OutputStream::try_default().unwrap();
        MusicStruct {
            sink: Sink::try_new(&amp;stream_handle).unwrap(),
            stream
        }

Edit:
The much better way to do this (and to have this work easier with threading) is to use

let (stream, stream_handle) = OutputStream::try_default().unwrap();
std::mem::forget(stream);

Which is used officially in the bevy game engine.

This is fine so long as you are not constructing multiple of these

huangapple
  • 本文由 发表于 2023年5月13日 11:05:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76240903.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定