2013-01-12 46 views
5

के बिना javafx मीडिया मेटाडेटा कैसे प्राप्त करें, इसलिए मैं इसे एक हफ्ते के लिए देख रहा हूं और हर समस्या को पढ़ने के बावजूद पढ़ रहा हूं लेकिन कोई भी मेरी समस्या के समान ही नहीं पूछ रहा था (रिवर्स इंजीनियरिंग अन्य समाधान जैसा मैं करता हूं कोई सफलता के साथ चाहते हैंश्रोता

समझाया गुफा शैली:।। मैं मेटाडाटा का उपयोग कर सूची बनाने के लिए कोशिश कर रहा हूँ

  1. मैं एक बहु संवाद के साथ खोल सकते हैं और अधिक से अधिक एक एमपी 3
  2. चयन मैं एक में फ़ाइल डाल ArrayList<File>
  3. मैं लो सेशन हालांकि एक पाश और निकालने मेटाडाटा के लिए बढ़ाया एक मीडिया चर
  4. जानकारी का उपयोग मेटाडाटा के लिए ("कलाकार" की तरह) के साथ फ़ाइलें क्या मैं

उदाहरण के लिए एक ArrayList में बचाने के लिए समस्या है चाहता हूँ

ArrayList<String> al; 
String path; 
public void open(){ 
    files=chooser.showOpenMultipleDialog(new Stage()); 
    for(File f:files){    
     path=f.getPath(); 
     Media media = new Media("file:/"+path.replace("\\", "/").replace(" ", "%20")); 
     al= new ArrayList<String>(); 
     media.getMetadata().addListener(new MapChangeListener<String, Object>() {     
      public void onChanged(Change<? extends String, ? extends Object> change) { 
       if (change.wasAdded()) { 
        if (change.getKey().equals("artist")) { 
         al.add((String) change.getValueAdded()); 
        } 
       } 
      } 
     }); 
    }//close for loop 
    //then i want to see the size of al like this 
    system.out.println(al.size()); 
    //then it returns 1 no matter how much file i selected 
    //when i system out "al" i get an empty string 

उत्तर

3

: कि श्रोता ही जो ArrayList<String> यह में कुछ भी नहीं के साथ एक वस्तु होने में परिणाम है जिस तरह से करने के बाद बढ़ाया पाश समाप्त हो गया है काम करता है

यहाँ एक नमूना है श्रोता जोड़ने के साथ मीडिया स्रोत मेटाडेटा को पढ़ने का दूसरा तरीका Mediaplayer .setOnReady() में उस जानकारी को निकाला जाता है; यहाँ जावा नियंत्रक वर्ग

सार्वजनिक वर्ग uiController लागू करता Initializable {

@FXML private Label label; 
@FXML private ListView<String> lv; 
@FXML private AnchorPane root; 
@FXML private Button button; 

private ObservableList<String> ol= FXCollections.observableArrayList(); 
private List<File> selectedFiles; 
private final Object obj= new Object(); 

@Override 
public void initialize(URL url, ResourceBundle rb) { 
    assert button != null : "fx:id=\"button\" was not injected: check your FXML file 'ui.fxml'."; 
    assert label != null : "fx:id=\"label\" was not injected: check your FXML file 'ui.fxml'."; 
    assert lv != null : "fx:id=\"lv\" was not injected: check your FXML file 'ui.fxml'."; 
    assert root != null : "fx:id=\"root\" was not injected: check your FXML file 'ui.fxml'."; 

    // initialize your logic here: all @FXML variables will have been injected 
    lv.setItems(ol); 
} 

@FXML private void open(ActionEvent event) { 
    FileChooser.ExtensionFilter extention= new FileChooser.ExtensionFilter("Music Files", "*.mp3","*.m4a","*.aif","*.wav","*.m3u","*.m3u8"); 
    FileChooser fc= new FileChooser(); 
    fc.setInitialDirectory(new File(System.getenv("userprofile"))); 
    fc.setTitle("Select File(s)"); 
    fc.getExtensionFilters().add(extention); 
    selectedFiles =fc.showOpenMultipleDialog(root.getScene().getWindow()); 
    if(selectedFiles != null &&!selectedFiles.isEmpty()){ 
     listFiles(); 
    } 
} 
/** 
* Convert each fie selected to its URI 
*/ 
private void listFiles(){ 
    try { 
     for (File file : selectedFiles) { 
      readMetaData(file.toURI().toString()); 
      synchronized(obj){ 
       obj.wait(100); 
      } 
     } 
    } catch (InterruptedException ex) { 
    } 
    System.gc(); 
} 
/** 
* Read a Media source metadata 
* Note: Sometimes the was unable to extract the metadata especially when 
* i have selected large number of files reasons i don't known why 
* @param mediaURI Media file URI 
*/ 
private void readMetaData(String mediaURI){ 
    final MediaPlayer mp= new MediaPlayer(new Media(mediaURI)); 
    mp.setOnReady(new Runnable() { 

     @Override 
     public void run() { 
      String artistName=(String) mp.getMedia().getMetadata().get("artist"); 
      ol.add(artistName); 
      synchronized(obj){//this is required since mp.setOnReady creates a new thread and our loopp in the main thread 
       obj.notify();// the loop has to wait unitl we are able to get the media metadata thats why use .wait() and .notify() to synce the two threads(main thread and MediaPlayer thread) 
      } 
     } 
    }); 
} 

} का एक उदाहरण हिस्सा है

कुछ परिवर्तन है कि बना दिया है मेटाडाटा से कलाकार का नाम स्टोर करने के लिए एक ObservableList प्रयोग किया जाता है

कोड में आप पाएंगे इस

 synchronized(obj){ 
        obj.wait(100); 
       }
मैं ऐसा इस वजह मीडियाप्लेयर .setOnReady() एक नया धागा बनाता है और पाश में है मुख्य अनुप्रयोग धागा, लूप को अन्य थ्रेड बनने से पहले कुछ समय तक इंतजार करना पड़ता है और हम मेटाडेटा निकालने में सक्षम होते हैं, और .setOnReady() में
 synchronized(obj){ 
        obj.notify; 
       }
मुख्य धागे को जागने के लिए लूप होता है इसलिए लूप अगले आइटम

मैं मानता हूं कि यह ऐसा करने का सबसे अच्छा समाधान नहीं हो सकता है, लेकिन फाइलों की सूची से JavaFx मीडिया मेटाडेटा को पढ़ने के तरीके के बारे में कोई बेहतर तरीका है, पूर्ण NetBeans परियोजना यहां पाया जा सकता https://docs.google.com/file/d/0BxDEmOcXqnCLSTFHbTVFcGIzT1E/edit?usp=sharing

प्लस जो मेटाडाटा के उपयोग expolits JavaFX का उपयोग कर एक छोटा सा MediaPlayer आवेदन बनाया है https://docs.google.com/file/d/0BxDEmOcXqnCLR1Z0VGN4ZlJkbUU/edit?usp=sharing

0

आप किसी एक मीडिया वस्तु के लिए मेटाडाटा को पुनः प्राप्त करने के लिए निम्न फ़ंक्शन का उपयोग कर सकते हैं:

public static void initializeMetaData(Media media) { 
    final Ref<Boolean> ready = new Ref<>(false); 

    MediaPlayer mediaPlayer = new MediaPlayer(media); 
    mediaPlayer.setOnReady(() -> { 
     synchronized (ready) { 
      ready.set(false); 
      ready.notify(); 
     } 
    }); 

    synchronized (ready) { 
     if (!ready.get()) { 
      try { 
       ready.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

हालांकि, एक JavaFX धागे से initializeMetaData फोन नहीं है, अन्यथा धागा एक गतिरोध में चलाता है।

पीएस: यह वास्तव में हास्यास्पद है कि किसी को ऐसा कामकाज बनाना है। मुझे आशा है कि भविष्य में मीडिया एक प्रारंभिक() विधि प्रदान करेगा जो यह काम करता है।

0

कि इस मुद्दे को मेरे समाधान यह था:

public class MediaListener implements MapChangeListener<String, Object> 
{ 
    public String title = null; 
    public String artist = null; 
    public String album = null; 

    private final Consumer<MediaListener> handler; 
    private boolean handled = false; 

    public MediaListener(Consumer<MediaListener> handler) 
    { 
     this.handler = handler; 
    } 

    @Override 
    public void onChanged(MapChangeListener.Change<? extends String, ?> ch) 
    { 
     if (ch.wasAdded()) 
     { 
      String key = ch.getKey(); 
      switch (key) 
      { 
       case "title": 
        title = (String) ch.getValueAdded(); 
        break; 
       case "artist": 
        artist = (String) ch.getValueAdded(); 
        break; 
       case "album": 
        album = (String) ch.getValueAdded(); 
        break; 
      } 

      if (!handled && title != null && artist != null && album != null) 
      { 
       handler.accept(this); 
       handled = true; 
      } 
     } 
    } 
} 

यह सबसे अच्छा तरीका है नहीं हो सकता है, लेकिन यह जिस तरह से फ़ाइल प्रति एक नया MediaPlayer बनाने की तुलना में क्लीनर है।

उदाहरण उपयोग:

Media media = Util.createMedia(path); 
media.getMetadata().addListener(new MediaListener((data) -> 
{ 
    // Use the data object to access the media 
}));