lots of ios file related updates, now use URLs internally. icons added.
@@ -13,4 +13,12 @@ void getSafeAreaInsets(void * component, float & top, float & bottom, float & le
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void disableAppNap();
 | 
					void disableAppNap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if JUCE_IOS
 | 
				
			||||||
 | 
					bool urlBookmarkToBinaryData(void * bookmark, const void * & retdata, size_t & retsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *binaryDataToUrlBookmark(const void * data, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,4 +59,23 @@ void getSafeAreaInsets(void * component, float & top, float & bottom, float & le
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool urlBookmarkToBinaryData(void * bookmark, const void * & retdata, size_t & retsize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NSData * data = (NSData*) bookmark;
 | 
				
			||||||
 | 
					    if (data && [data isKindOfClass:NSData.class]) {
 | 
				
			||||||
 | 
					        retdata = [data bytes];
 | 
				
			||||||
 | 
					        retsize = [data length];
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void * binaryDataToUrlBookmark(const void * data, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NSData * nsdata = [[NSData alloc] initWithBytes:data length:size];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return nsdata;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,10 +71,10 @@ public:
 | 
				
			|||||||
            return &m_readbuf;
 | 
					            return &m_readbuf;
 | 
				
			||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
	bool openAudioFile(File file) override
 | 
						bool openAudioFile(const URL & url) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
		m_silenceoutputted = 0;
 | 
							m_silenceoutputted = 0;
 | 
				
			||||||
		AudioFormatReader* reader = m_manager->createReaderFor(file);
 | 
							AudioFormatReader* reader = m_manager->createReaderFor(url.getLocalFile());
 | 
				
			||||||
        if (reader)
 | 
					        if (reader)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
			ScopedLock locker(m_mutex);
 | 
								ScopedLock locker(m_mutex);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ public:
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		[[nodiscard]] virtual bool openAudioFile(File file)=0;
 | 
							[[nodiscard]] virtual bool openAudioFile(const URL & url)=0;
 | 
				
			||||||
		virtual void close()=0;
 | 
							virtual void close()=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		virtual int readNextBlock(AudioBuffer<float>& abuf, int smps, int numchans)=0;
 | 
							virtual int readNextBlock(AudioBuffer<float>& abuf, int smps, int numchans)=0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -158,7 +158,7 @@ void StretchAudioSource::setAudioBufferAsInputSource(AudioBuffer<float>* buf, in
 | 
				
			|||||||
	m_inputfile->setAudioBuffer(buf, sr, len);
 | 
						m_inputfile->setAudioBuffer(buf, sr, len);
 | 
				
			||||||
	m_seekpos = 0.0;
 | 
						m_seekpos = 0.0;
 | 
				
			||||||
    m_audiobuffer_is_source = true;
 | 
					    m_audiobuffer_is_source = true;
 | 
				
			||||||
	m_curfile = File();
 | 
						m_curfile = URL();
 | 
				
			||||||
	if (m_playrange.isEmpty())
 | 
						if (m_playrange.isEmpty())
 | 
				
			||||||
		setPlayRange({ 0.0,1.0 });
 | 
							setPlayRange({ 0.0,1.0 });
 | 
				
			||||||
	++m_param_change_count;
 | 
						++m_param_change_count;
 | 
				
			||||||
@@ -505,12 +505,12 @@ bool StretchAudioSource::isLooping() const
 | 
				
			|||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String StretchAudioSource::setAudioFile(File file)
 | 
					String StretchAudioSource::setAudioFile(const URL & url)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ScopedLock locker(m_cs);
 | 
						ScopedLock locker(m_cs);
 | 
				
			||||||
	if (m_inputfile->openAudioFile(file))
 | 
						if (m_inputfile->openAudioFile(url))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_curfile = file;
 | 
							m_curfile = url;
 | 
				
			||||||
		m_firstbuffer = true;
 | 
							m_firstbuffer = true;
 | 
				
			||||||
        m_audiobuffer_is_source = false;
 | 
					        m_audiobuffer_is_source = false;
 | 
				
			||||||
		return String();
 | 
							return String();
 | 
				
			||||||
@@ -518,7 +518,7 @@ String StretchAudioSource::setAudioFile(File file)
 | 
				
			|||||||
	return "Could not open file";
 | 
						return "Could not open file";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
File StretchAudioSource::getAudioFile()
 | 
					URL StretchAudioSource::getAudioFile()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return m_curfile;
 | 
						return m_curfile;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,8 +46,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	bool isLooping() const override;
 | 
						bool isLooping() const override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	String setAudioFile(File file);
 | 
						String setAudioFile(const URL & file);
 | 
				
			||||||
	File getAudioFile();
 | 
						URL getAudioFile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AudioBuffer<float>* getSourceAudioBuffer();
 | 
					    AudioBuffer<float>* getSourceAudioBuffer();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -148,7 +148,7 @@ private:
 | 
				
			|||||||
	
 | 
						
 | 
				
			||||||
	bool m_stream_end_reached = false;
 | 
						bool m_stream_end_reached = false;
 | 
				
			||||||
	int64_t m_output_silence_counter = 0;
 | 
						int64_t m_output_silence_counter = 0;
 | 
				
			||||||
	File m_curfile;
 | 
						URL m_curfile;
 | 
				
			||||||
    bool m_audiobuffer_is_source = false;
 | 
					    bool m_audiobuffer_is_source = false;
 | 
				
			||||||
	int64_t m_maxloops = 0;
 | 
						int64_t m_maxloops = 0;
 | 
				
			||||||
	std::unique_ptr<WDL_Resampler> m_resampler;
 | 
						std::unique_ptr<WDL_Resampler> m_resampler;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -160,11 +160,20 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor(Pau
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_parcomps[cpi_num_inchans]->getSlider()->setSliderStyle(Slider::SliderStyle::IncDecButtons);
 | 
					    m_parcomps[cpi_num_inchans]->getSlider()->setSliderStyle(Slider::SliderStyle::IncDecButtons);
 | 
				
			||||||
    m_parcomps[cpi_num_inchans]->getSlider()->setTextBoxStyle(Slider::TextEntryBoxPosition::TextBoxLeft, false, 30, 34);
 | 
					    m_parcomps[cpi_num_inchans]->getSlider()->setTextBoxStyle(Slider::TextEntryBoxPosition::TextBoxLeft, false, 30, 34);
 | 
				
			||||||
    m_parcomps[cpi_num_outchans]->getSlider()->setSliderStyle(Slider::SliderStyle::IncDecButtons);
 | 
					    m_parcomps[cpi_num_outchans]->getSlider()->setSliderStyle(Slider::SliderStyle::IncDecButtons);
 | 
				
			||||||
    m_parcomps[cpi_num_outchans]->getSlider()->setTextBoxStyle(Slider::TextEntryBoxPosition::TextBoxLeft, false, 30, 34);
 | 
					    m_parcomps[cpi_num_outchans]->getSlider()->setTextBoxStyle(Slider::TextEntryBoxPosition::TextBoxLeft, false, 30, 34);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if JUCE_IOS
 | 
				
			||||||
 | 
					    // just don't include chan counts on ios for now
 | 
				
			||||||
 | 
					    removeChildComponent(m_parcomps[cpi_num_inchans].get());
 | 
				
			||||||
 | 
					    removeChildComponent(m_parcomps[cpi_num_outchans].get());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_groupviewport = std::make_unique<Viewport>();
 | 
					    m_groupviewport = std::make_unique<Viewport>();
 | 
				
			||||||
    m_groupcontainer = std::make_unique<Component>();
 | 
					    m_groupcontainer = std::make_unique<Component>();
 | 
				
			||||||
    m_groupviewport->setViewedComponent(m_groupcontainer.get(), false);
 | 
					    m_groupviewport->setViewedComponent(m_groupcontainer.get(), false);
 | 
				
			||||||
@@ -581,6 +590,7 @@ void PaulstretchpluginAudioProcessorEditor::resized()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_capture_trigger]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
					    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_capture_trigger]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
				
			||||||
    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_passthrough]).withMargin(margin).withFlex(1.5).withMaxWidth(200));
 | 
					    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_passthrough]).withMargin(margin).withFlex(1.5).withMaxWidth(200));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_pause_enabled]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
					    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_pause_enabled]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
				
			||||||
    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_freeze]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
					    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_freeze]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
				
			||||||
    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_bypass_stretch]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
					    togglesbox.items.add(FlexItem(toggleminw, togglerowheight, *m_parcomps[cpi_bypass_stretch]).withMargin(margin).withFlex(1).withMaxWidth(200));
 | 
				
			||||||
@@ -596,6 +606,8 @@ void PaulstretchpluginAudioProcessorEditor::resized()
 | 
				
			|||||||
    volbox.alignContent = FlexBox::AlignContent::flexStart;
 | 
					    volbox.alignContent = FlexBox::AlignContent::flexStart;
 | 
				
			||||||
    volbox.items.add(FlexItem(minitemw*0.75f, rowheight, *m_parcomps[cpi_main_volume]).withMargin(margin).withFlex(1));
 | 
					    volbox.items.add(FlexItem(minitemw*0.75f, rowheight, *m_parcomps[cpi_main_volume]).withMargin(margin).withFlex(1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !JUCE_IOS
 | 
				
			||||||
    FlexBox inoutbox;
 | 
					    FlexBox inoutbox;
 | 
				
			||||||
    int inoutminw = 170;
 | 
					    int inoutminw = 170;
 | 
				
			||||||
    int inoutmaxw = 200;
 | 
					    int inoutmaxw = 200;
 | 
				
			||||||
@@ -605,6 +617,7 @@ void PaulstretchpluginAudioProcessorEditor::resized()
 | 
				
			|||||||
    inoutbox.items.add(FlexItem(inoutminw, rowheight, *m_parcomps[cpi_num_outchans]).withMargin(margin).withFlex(0.5).withMaxWidth(inoutmaxw));
 | 
					    inoutbox.items.add(FlexItem(inoutminw, rowheight, *m_parcomps[cpi_num_outchans]).withMargin(margin).withFlex(0.5).withMaxWidth(inoutmaxw));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    volbox.items.add(FlexItem(2*inoutminw, rowheight, inoutbox).withMargin(margin).withFlex(1.5).withMaxWidth(2*inoutmaxw + 10));
 | 
					    volbox.items.add(FlexItem(2*inoutminw, rowheight, inoutbox).withMargin(margin).withFlex(1.5).withMaxWidth(2*inoutmaxw + 10));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    volbox.performLayout(Rectangle<int>(0,0,w - 2*margin,400)); // test run to calculate actual used height
 | 
					    volbox.performLayout(Rectangle<int>(0,0,w - 2*margin,400)); // test run to calculate actual used height
 | 
				
			||||||
    int volh = volbox.items.getLast().currentBounds.getBottom() + volbox.items.getLast().margin.bottom;
 | 
					    int volh = volbox.items.getLast().currentBounds.getBottom() + volbox.items.getLast().margin.bottom;
 | 
				
			||||||
@@ -888,8 +901,9 @@ void PaulstretchpluginAudioProcessorEditor::filesDropped(const StringArray & fil
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	if (files.size() > 0)
 | 
						if (files.size() > 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		File f(files[0]);
 | 
					        File file(files[0]);
 | 
				
			||||||
		processor.setAudioFile(f);
 | 
							URL url = URL(file);
 | 
				
			||||||
 | 
							processor.setAudioFile(url);
 | 
				
			||||||
		toFront(true);
 | 
							toFront(true);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -900,13 +914,8 @@ void PaulstretchpluginAudioProcessorEditor::urlOpened(const URL& url)
 | 
				
			|||||||
    std::unique_ptr<InputStream> wi (url.createInputStream (false));
 | 
					    std::unique_ptr<InputStream> wi (url.createInputStream (false));
 | 
				
			||||||
    if (wi != nullptr)
 | 
					    if (wi != nullptr)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        File file = url.getLocalFile();
 | 
					        DBG("Attempting to load after input stream create: " << url.toString(false));
 | 
				
			||||||
        DBG("Attempting to load after input stream create: " << file.getFullPathName());
 | 
					        processor.setAudioFile(url);
 | 
				
			||||||
        processor.setAudioFile(file);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        File file = url.getLocalFile();
 | 
					 | 
				
			||||||
        DBG("Attempting to load after no input stream create: " << file.getFullPathName());
 | 
					 | 
				
			||||||
        processor.setAudioFile(file);
 | 
					 | 
				
			||||||
    } 
 | 
					    } 
 | 
				
			||||||
    toFront(true);
 | 
					    toFront(true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1048,7 +1057,7 @@ void PaulstretchpluginAudioProcessorEditor::toggleFileBrowser()
 | 
				
			|||||||
                DBG("Attempting to load from: " << file.getFullPathName());
 | 
					                DBG("Attempting to load from: " << file.getFullPathName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                //curropendir = file.getParentDirectory();
 | 
					                //curropendir = file.getParentDirectory();
 | 
				
			||||||
                processor.setAudioFile(file);
 | 
					                processor.setAudioFile(url);
 | 
				
			||||||
                processor.m_propsfile->m_props_file->setValue("importfilefolder", file.getParentDirectory().getFullPathName());
 | 
					                processor.m_propsfile->m_props_file->setValue("importfilefolder", file.getParentDirectory().getFullPathName());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1223,7 +1232,7 @@ void WaveformComponent::paint(Graphics & g)
 | 
				
			|||||||
		g.fillRect(normalizedToViewX<int>(m_rec_pos), m_topmargin, 1, getHeight() - m_topmargin);
 | 
							g.fillRect(normalizedToViewX<int>(m_rec_pos), m_topmargin, 1, getHeight() - m_topmargin);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	g.setColour(Colours::aqua);
 | 
						g.setColour(Colours::aqua);
 | 
				
			||||||
	g.drawText(GetFileCallback().getFileName(), 2, m_topmargin + 2, getWidth(), 20, Justification::topLeft);
 | 
						g.drawText(URL::removeEscapeChars(GetFileCallback().getFileName()), 2, m_topmargin + 2, getWidth(), 20, Justification::topLeft);
 | 
				
			||||||
	g.drawText(secondsToString2(thumblen), getWidth() - 200, m_topmargin + 2, 200, 20, Justification::topRight);
 | 
						g.drawText(secondsToString2(thumblen), getWidth() - 200, m_topmargin + 2, 200, 20, Justification::topRight);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2366,7 +2375,7 @@ void MyFileBrowserComponent::fileClicked(const File & file, const MouseEvent & e
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void MyFileBrowserComponent::fileDoubleClicked(const File & file)
 | 
					void MyFileBrowserComponent::fileDoubleClicked(const File & file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	m_proc.setAudioFile(file);
 | 
						m_proc.setAudioFile(URL(file));
 | 
				
			||||||
	m_proc.m_propsfile->m_props_file->setValue("importfilefolder", file.getParentDirectory().getFullPathName());
 | 
						m_proc.m_propsfile->m_props_file->setValue("importfilefolder", file.getParentDirectory().getFullPathName());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -189,7 +189,7 @@ public:
 | 
				
			|||||||
	std::function<double()> CursorPosCallback;
 | 
						std::function<double()> CursorPosCallback;
 | 
				
			||||||
	std::function<void(double)> SeekCallback;
 | 
						std::function<void(double)> SeekCallback;
 | 
				
			||||||
	std::function<void(Range<double>, int)> TimeSelectionChangedCallback;
 | 
						std::function<void(Range<double>, int)> TimeSelectionChangedCallback;
 | 
				
			||||||
	std::function<File()> GetFileCallback;
 | 
						std::function<URL()> GetFileCallback;
 | 
				
			||||||
	std::function<void(Range<double>)> ViewRangeChangedCallback;
 | 
						std::function<void(Range<double>)> ViewRangeChangedCallback;
 | 
				
			||||||
	void mouseDown(const MouseEvent& e) override;
 | 
						void mouseDown(const MouseEvent& e) override;
 | 
				
			||||||
	void mouseUp(const MouseEvent& e) override;
 | 
						void mouseUp(const MouseEvent& e) override;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,8 @@ www.gnu.org/licenses
 | 
				
			|||||||
#include <set>
 | 
					#include <set>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#import "CrossPlatformUtils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef WIN32
 | 
					#ifdef WIN32
 | 
				
			||||||
#undef min
 | 
					#undef min
 | 
				
			||||||
#undef max
 | 
					#undef max
 | 
				
			||||||
@@ -66,20 +68,21 @@ m_bufferingthread("pspluginprebufferthread"), m_is_stand_alone_offline(is_stand_
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	m_filechoose_callback = [this](const FileChooser& chooser)
 | 
						m_filechoose_callback = [this](const FileChooser& chooser)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		File resu = chooser.getResult();
 | 
							URL resu = chooser.getURLResult();
 | 
				
			||||||
		String pathname = resu.getFullPathName();
 | 
							//String pathname = resu.getFullPathName();
 | 
				
			||||||
		if (pathname.startsWith("/localhost"))
 | 
							//if (pathname.startsWith("/localhost"))
 | 
				
			||||||
		{
 | 
							//{
 | 
				
			||||||
			pathname = pathname.substring(10);
 | 
							//	pathname = pathname.substring(10);
 | 
				
			||||||
			resu = File(pathname);
 | 
							//	resu = File(pathname);
 | 
				
			||||||
		}
 | 
							//}
 | 
				
			||||||
		m_propsfile->m_props_file->setValue("importfilefolder", resu.getParentDirectory().getFullPathName());
 | 
					        if (!resu.isEmpty()) {
 | 
				
			||||||
 | 
					            m_propsfile->m_props_file->setValue("importfilefolder", resu.getLocalFile().getParentDirectory().getFullPathName());
 | 
				
			||||||
            String loaderr = setAudioFile(resu);
 | 
					            String loaderr = setAudioFile(resu);
 | 
				
			||||||
            if (auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor()); ed != nullptr)
 | 
					            if (auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor()); ed != nullptr)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ed->m_last_err = loaderr;
 | 
					                ed->m_last_err = loaderr;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
		
 | 
					        }
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	m_playposinfo.timeInSeconds = 0.0;
 | 
						m_playposinfo.timeInSeconds = 0.0;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
@@ -268,9 +271,22 @@ ValueTree PaulstretchpluginAudioProcessor::getStateTree(bool ignoreoptions, bool
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	ValueTree paramtree("paulstretch3pluginstate");
 | 
						ValueTree paramtree("paulstretch3pluginstate");
 | 
				
			||||||
	storeToTreeProperties(paramtree, nullptr, getParameters(), { getBoolParameter(cpi_capture_trigger) });
 | 
						storeToTreeProperties(paramtree, nullptr, getParameters(), { getBoolParameter(cpi_capture_trigger) });
 | 
				
			||||||
    if (m_current_file != File() && ignorefile == false)
 | 
					    if (m_current_file != URL() && ignorefile == false)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		paramtree.setProperty("importedfile", m_current_file.getFullPathName(), nullptr);
 | 
							paramtree.setProperty("importedfile", m_current_file.toString(false), nullptr);
 | 
				
			||||||
 | 
					#if JUCE_IOS
 | 
				
			||||||
 | 
					        // store bookmark data if necessary
 | 
				
			||||||
 | 
					        if (void * bookmark = getURLBookmark(m_current_file)) {
 | 
				
			||||||
 | 
					            const void * data = nullptr;
 | 
				
			||||||
 | 
					            size_t datasize = 0;
 | 
				
			||||||
 | 
					            if (urlBookmarkToBinaryData(bookmark, data, datasize)) {
 | 
				
			||||||
 | 
					                DBG("Audio file has bookmark, storing it in state, size: " << datasize);
 | 
				
			||||||
 | 
					                paramtree.setProperty("importedfile_bookmark", var(data, datasize), nullptr);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                DBG("Bookmark is not valid!");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto specorder = m_stretch_source->getSpectrumProcessOrder();
 | 
						auto specorder = m_stretch_source->getSpectrumProcessOrder();
 | 
				
			||||||
	paramtree.setProperty("numspectralstagesb", (int)specorder.size(), nullptr);
 | 
						paramtree.setProperty("numspectralstagesb", (int)specorder.size(), nullptr);
 | 
				
			||||||
@@ -343,9 +359,30 @@ void PaulstretchpluginAudioProcessor::setStateFromTree(ValueTree tree)
 | 
				
			|||||||
		if (m_load_file_with_state == true)
 | 
							if (m_load_file_with_state == true)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
            String fn = tree.getProperty("importedfile");
 | 
					            String fn = tree.getProperty("importedfile");
 | 
				
			||||||
			if (fn.isEmpty() == false)
 | 
								if (fn.isNotEmpty())
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				setAudioFile(File(fn));
 | 
					                URL url(fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (!url.isLocalFile()) {
 | 
				
			||||||
 | 
					                    // reconstruct just in case imported file string was not a URL
 | 
				
			||||||
 | 
					                    url = URL(File(fn));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if JUCE_IOS
 | 
				
			||||||
 | 
					                // check for bookmark
 | 
				
			||||||
 | 
					                auto bptr = tree.getPropertyPointer("importedfile_bookmark");
 | 
				
			||||||
 | 
					                if (bptr) {
 | 
				
			||||||
 | 
					                    if (auto * block = bptr->getBinaryData()) {
 | 
				
			||||||
 | 
					                        DBG("Has file bookmark");
 | 
				
			||||||
 | 
					                        void * bookmark = binaryDataToUrlBookmark(block->getData(), block->getSize());
 | 
				
			||||||
 | 
					                        setURLBookmark(url, bookmark);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    DBG("no url bookmark found");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                setAudioFile(url);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		m_state_dirty = true;
 | 
							m_state_dirty = true;
 | 
				
			||||||
@@ -546,7 +583,7 @@ void PaulstretchpluginAudioProcessor::saveCaptureBuffer()
 | 
				
			|||||||
				jassert(sourcebuffer->getNumSamples() > 0);
 | 
									jassert(sourcebuffer->getNumSamples() > 0);
 | 
				
			||||||
				
 | 
									
 | 
				
			||||||
				writer->writeFromAudioSampleBuffer(*sourcebuffer, 0, sourcebuffer->getNumSamples());
 | 
									writer->writeFromAudioSampleBuffer(*sourcebuffer, 0, sourcebuffer->getNumSamples());
 | 
				
			||||||
				m_current_file = outfile;
 | 
									m_current_file = URL(outfile);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@@ -982,7 +1019,7 @@ void PaulstretchpluginAudioProcessor::setRecordingEnabled(bool b)
 | 
				
			|||||||
	if (b == true)
 | 
						if (b == true)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_using_memory_buffer = true;
 | 
							m_using_memory_buffer = true;
 | 
				
			||||||
		m_current_file = File();
 | 
							m_current_file = URL();
 | 
				
			||||||
		int numchans = *m_inchansparam;
 | 
							int numchans = *m_inchansparam;
 | 
				
			||||||
		m_recbuffer.setSize(numchans, m_max_reclen*getSampleRateChecked()+4096,false,false,true);
 | 
							m_recbuffer.setSize(numchans, m_max_reclen*getSampleRateChecked()+4096,false,false,true);
 | 
				
			||||||
		m_recbuffer.clear();
 | 
							m_recbuffer.clear();
 | 
				
			||||||
@@ -1008,33 +1045,44 @@ double PaulstretchpluginAudioProcessor::getRecordingPositionPercent()
 | 
				
			|||||||
	return 1.0 / m_recbuffer.getNumSamples()*m_rec_pos;
 | 
						return 1.0 / m_recbuffer.getNumSamples()*m_rec_pos;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String PaulstretchpluginAudioProcessor::setAudioFile(File f)
 | 
					String PaulstretchpluginAudioProcessor::setAudioFile(const URL & url)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto ai = unique_from_raw(m_afm->createReaderFor(f));
 | 
					    // this handles any permissions stuff (needed on ios)
 | 
				
			||||||
 | 
					    std::unique_ptr<InputStream> wi (url.createInputStream (false));
 | 
				
			||||||
 | 
					    File file = url.getLocalFile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto ai = unique_from_raw(m_afm->createReaderFor(file));
 | 
				
			||||||
	if (ai != nullptr)
 | 
						if (ai != nullptr)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (ai->numChannels > 8)
 | 
							if (ai->numChannels > 8)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			return "Too many channels in file "+f.getFullPathName();
 | 
								return "Too many channels in file "+ file.getFullPathName();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (ai->bitsPerSample>32)
 | 
							if (ai->bitsPerSample>32)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			return "Too high bit depth in file " + f.getFullPathName();
 | 
								return "Too high bit depth in file " + file.getFullPathName();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (m_thumb)
 | 
							if (m_thumb)
 | 
				
			||||||
			m_thumb->setSource(new FileInputSource(f));
 | 
								m_thumb->setSource(new FileInputSource(file));
 | 
				
			||||||
		ScopedLock locker(m_cs);
 | 
							ScopedLock locker(m_cs);
 | 
				
			||||||
		m_stretch_source->setAudioFile(f);
 | 
							m_stretch_source->setAudioFile(url);
 | 
				
			||||||
		//Range<double> currange{ *getFloatParameter(cpi_soundstart),*getFloatParameter(cpi_soundend) };
 | 
							//Range<double> currange{ *getFloatParameter(cpi_soundstart),*getFloatParameter(cpi_soundend) };
 | 
				
			||||||
		//if (currange.contains(m_stretch_source->getInfilePositionPercent())==false)
 | 
							//if (currange.contains(m_stretch_source->getInfilePositionPercent())==false)
 | 
				
			||||||
			m_stretch_source->seekPercent(*getFloatParameter(cpi_soundstart));
 | 
								m_stretch_source->seekPercent(*getFloatParameter(cpi_soundstart));
 | 
				
			||||||
		m_current_file = f;
 | 
							m_current_file = url;
 | 
				
			||||||
        m_current_file_date = m_current_file.getLastModificationTime();
 | 
					
 | 
				
			||||||
 | 
					#if JUCE_IOS
 | 
				
			||||||
 | 
					        if (void * bookmark = getURLBookmark(m_current_file)) {
 | 
				
			||||||
 | 
					            DBG("Loaded audio file has bookmark");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_current_file_date = file.getLastModificationTime();
 | 
				
			||||||
		m_using_memory_buffer = false;
 | 
							m_using_memory_buffer = false;
 | 
				
			||||||
		setDirty();
 | 
							setDirty();
 | 
				
			||||||
		return String();
 | 
							return String();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return "Could not open file " + f.getFullPathName();
 | 
						return "Could not open file " + file.getFullPathName();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Range<double> PaulstretchpluginAudioProcessor::getTimeSelection()
 | 
					Range<double> PaulstretchpluginAudioProcessor::getTimeSelection()
 | 
				
			||||||
@@ -1106,7 +1154,7 @@ pointer_sized_int PaulstretchpluginAudioProcessor::handleVstPluginCanDo(int32 in
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			String fn(CharPointer_UTF8((char*)value));
 | 
								String fn(CharPointer_UTF8((char*)value));
 | 
				
			||||||
			//std::cout << "host requested to set audio file " << fn << "\n";
 | 
								//std::cout << "host requested to set audio file " << fn << "\n";
 | 
				
			||||||
			auto err = setAudioFile(File(fn));
 | 
								auto err = setAudioFile(URL(fn));
 | 
				
			||||||
			if (err.isEmpty()==false)
 | 
								if (err.isEmpty()==false)
 | 
				
			||||||
				std::cout << err << "\n";
 | 
									std::cout << err << "\n";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -1124,7 +1172,7 @@ pointer_sized_int PaulstretchpluginAudioProcessor::handleVstManufacturerSpecific
 | 
				
			|||||||
void PaulstretchpluginAudioProcessor::finishRecording(int lenrecording)
 | 
					void PaulstretchpluginAudioProcessor::finishRecording(int lenrecording)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	m_is_recording = false;
 | 
						m_is_recording = false;
 | 
				
			||||||
	m_current_file = File();
 | 
						m_current_file = URL();
 | 
				
			||||||
	m_stretch_source->setAudioBufferAsInputSource(&m_recbuffer, getSampleRateChecked(), lenrecording);
 | 
						m_stretch_source->setAudioBufferAsInputSource(&m_recbuffer, getSampleRateChecked(), lenrecording);
 | 
				
			||||||
	*getFloatParameter(cpi_soundstart) = 0.0f;
 | 
						*getFloatParameter(cpi_soundstart) = 0.0f;
 | 
				
			||||||
	*getFloatParameter(cpi_soundend) = jlimit<double>(0.01, 1.0, 1.0 / lenrecording * m_rec_count);
 | 
						*getFloatParameter(cpi_soundend) = jlimit<double>(0.01, 1.0, 1.0 / lenrecording * m_rec_count);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -200,8 +200,8 @@ public:
 | 
				
			|||||||
	void setRecordingEnabled(bool b);
 | 
						void setRecordingEnabled(bool b);
 | 
				
			||||||
	bool isRecordingEnabled() { return m_is_recording; }
 | 
						bool isRecordingEnabled() { return m_is_recording; }
 | 
				
			||||||
	double getRecordingPositionPercent();
 | 
						double getRecordingPositionPercent();
 | 
				
			||||||
	String setAudioFile(File f);
 | 
						String setAudioFile(const URL& url);
 | 
				
			||||||
	File getAudioFile() { return m_current_file; }
 | 
						URL getAudioFile() { return m_current_file; }
 | 
				
			||||||
	Range<double> getTimeSelection();
 | 
						Range<double> getTimeSelection();
 | 
				
			||||||
	SharedResourcePointer<AudioFormatManager> m_afm;
 | 
						SharedResourcePointer<AudioFormatManager> m_afm;
 | 
				
			||||||
    SharedResourcePointer<MyPropertiesFile> m_propsfile;
 | 
					    SharedResourcePointer<MyPropertiesFile> m_propsfile;
 | 
				
			||||||
@@ -261,7 +261,7 @@ private:
 | 
				
			|||||||
	bool m_using_memory_buffer = true;
 | 
						bool m_using_memory_buffer = true;
 | 
				
			||||||
	int m_cur_num_out_chans = 2;
 | 
						int m_cur_num_out_chans = 2;
 | 
				
			||||||
	CriticalSection m_cs;
 | 
						CriticalSection m_cs;
 | 
				
			||||||
	File m_current_file;
 | 
						URL m_current_file;
 | 
				
			||||||
    Time m_current_file_date;
 | 
					    Time m_current_file_date;
 | 
				
			||||||
	bool m_is_recording = false;
 | 
						bool m_is_recording = false;
 | 
				
			||||||
	TimeSliceThread m_bufferingthread;
 | 
						TimeSliceThread m_bufferingthread;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								images/paulxstretch_icon_1024.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 147 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/paulxstretch_icon_1024_rounded.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 147 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/paulxstretch_icon_256.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 24 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/paulxstretch_icon_256_rounded.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 25 KiB  | 
| 
		 Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB  | 
| 
		 Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB  | 
@@ -13,6 +13,14 @@
 | 
				
			|||||||
              headerPath="

" pluginFormats="buildAU,buildStandalone,buildVST3"
 | 
					              headerPath="

" pluginFormats="buildAU,buildStandalone,buildVST3"
 | 
				
			||||||
              jucerFormatVersion="1" useAppConfig="0" defines="JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1">
 | 
					              jucerFormatVersion="1" useAppConfig="0" defines="JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1">
 | 
				
			||||||
  <MAINGROUP id="nozXHl" name="PaulXStretch">
 | 
					  <MAINGROUP id="nozXHl" name="PaulXStretch">
 | 
				
			||||||
 | 
					    <GROUP id="{F2FF95A8-60F3-2FB2-CE4F-933A28090D76}" name="images">
 | 
				
			||||||
 | 
					      <FILE id="Yny1oQ" name="paulxstretch_icon_256_rounded.png" compile="0"
 | 
				
			||||||
 | 
					            resource="0" file="images/paulxstretch_icon_256_rounded.png"/>
 | 
				
			||||||
 | 
					      <FILE id="hG1CYd" name="paulxstretch_icon_1024_rounded.png" compile="0"
 | 
				
			||||||
 | 
					            resource="0" file="images/paulxstretch_icon_1024_rounded.png"/>
 | 
				
			||||||
 | 
					      <FILE id="PLvX8b" name="power.svg" compile="0" resource="1" file="images/power.svg"/>
 | 
				
			||||||
 | 
					      <FILE id="PMRzOf" name="power_sel.svg" compile="0" resource="1" file="images/power_sel.svg"/>
 | 
				
			||||||
 | 
					    </GROUP>
 | 
				
			||||||
    <GROUP id="{03DA6B32-F666-FF60-F168-4385D0847058}" name="Source">
 | 
					    <GROUP id="{03DA6B32-F666-FF60-F168-4385D0847058}" name="Source">
 | 
				
			||||||
      <GROUP id="{3B6D1AF9-E53E-2F78-24A5-D12A34009E6A}" name="PS_Source">
 | 
					      <GROUP id="{3B6D1AF9-E53E-2F78-24A5-D12A34009E6A}" name="PS_Source">
 | 
				
			||||||
        <FILE id="gDsFRp" name="globals.h" compile="0" resource="0" file="Source/PS_Source/globals.h"/>
 | 
					        <FILE id="gDsFRp" name="globals.h" compile="0" resource="0" file="Source/PS_Source/globals.h"/>
 | 
				
			||||||
@@ -52,8 +60,6 @@
 | 
				
			|||||||
            file="Source/PluginProcessor.cpp"/>
 | 
					            file="Source/PluginProcessor.cpp"/>
 | 
				
			||||||
      <FILE id="pt5tX8" name="PluginProcessor.h" compile="0" resource="0"
 | 
					      <FILE id="pt5tX8" name="PluginProcessor.h" compile="0" resource="0"
 | 
				
			||||||
            file="Source/PluginProcessor.h"/>
 | 
					            file="Source/PluginProcessor.h"/>
 | 
				
			||||||
      <FILE id="id3jov" name="power.svg" compile="0" resource="1" file="Source/power.svg"/>
 | 
					 | 
				
			||||||
      <FILE id="qKY0Ks" name="power_sel.svg" compile="0" resource="1" file="Source/power_sel.svg"/>
 | 
					 | 
				
			||||||
      <FILE id="KcXfhC" name="ps3_BufferingAudioSource.cpp" compile="1" resource="0"
 | 
					      <FILE id="KcXfhC" name="ps3_BufferingAudioSource.cpp" compile="1" resource="0"
 | 
				
			||||||
            file="Source/ps3_BufferingAudioSource.cpp"/>
 | 
					            file="Source/ps3_BufferingAudioSource.cpp"/>
 | 
				
			||||||
      <FILE id="oWbh5E" name="ps3_BufferingAudioSource.h" compile="0" resource="0"
 | 
					      <FILE id="oWbh5E" name="ps3_BufferingAudioSource.h" compile="0" resource="0"
 | 
				
			||||||
@@ -69,7 +75,8 @@
 | 
				
			|||||||
    <XCODE_MAC targetFolder="Builds/MacOSX" externalLibraries="fftw3f" microphonePermissionNeeded="1"
 | 
					    <XCODE_MAC targetFolder="Builds/MacOSX" externalLibraries="fftw3f" microphonePermissionNeeded="1"
 | 
				
			||||||
               microphonePermissionsText="This application requires audio input to capture live audio for processing"
 | 
					               microphonePermissionsText="This application requires audio input to capture live audio for processing"
 | 
				
			||||||
               hardenedRuntime="1" hardenedRuntimeOptions="com.apple.security.device.audio-input"
 | 
					               hardenedRuntime="1" hardenedRuntimeOptions="com.apple.security.device.audio-input"
 | 
				
			||||||
               xcodeValidArchs="arm64,x86_64" buildNumber="100" applicationCategory="public.app-category.music">
 | 
					               xcodeValidArchs="arm64,x86_64" buildNumber="100" applicationCategory="public.app-category.music"
 | 
				
			||||||
 | 
					               smallIcon="Yny1oQ" bigIcon="hG1CYd">
 | 
				
			||||||
      <CONFIGURATIONS>
 | 
					      <CONFIGURATIONS>
 | 
				
			||||||
        <CONFIGURATION name="Debug" enablePluginBinaryCopyStep="1" isDebug="1" optimisation="1"
 | 
					        <CONFIGURATION name="Debug" enablePluginBinaryCopyStep="1" isDebug="1" optimisation="1"
 | 
				
			||||||
                       linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source
Source/WDL
${HOME}/devstatic/include
"
 | 
					                       linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source
Source/WDL
${HOME}/devstatic/include
"
 | 
				
			||||||
@@ -101,7 +108,7 @@
 | 
				
			|||||||
      </MODULEPATHS>
 | 
					      </MODULEPATHS>
 | 
				
			||||||
    </XCODE_MAC>
 | 
					    </XCODE_MAC>
 | 
				
			||||||
    <VS2017 targetFolder="Builds/VisualStudio2017" externalLibraries="C:\ProgrammingProjects\fftw-3.3.6-pl2\fftw-3.3-libs\x64\Static-Release\libfftwf-3.3.lib"
 | 
					    <VS2017 targetFolder="Builds/VisualStudio2017" externalLibraries="C:\ProgrammingProjects\fftw-3.3.6-pl2\fftw-3.3-libs\x64\Static-Release\libfftwf-3.3.lib"
 | 
				
			||||||
            extraDefs="">
 | 
					            extraDefs="" smallIcon="Yny1oQ" bigIcon="hG1CYd">
 | 
				
			||||||
      <CONFIGURATIONS>
 | 
					      <CONFIGURATIONS>
 | 
				
			||||||
        <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
 | 
					        <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
 | 
				
			||||||
                       debugInformationFormat="ProgramDatabase" enablePluginBinaryCopyStep="1"
 | 
					                       debugInformationFormat="ProgramDatabase" enablePluginBinaryCopyStep="1"
 | 
				
			||||||
@@ -131,7 +138,8 @@
 | 
				
			|||||||
        <MODULEPATH id="juce_dsp" path="../gitrepos/JUCE/modules"/>
 | 
					        <MODULEPATH id="juce_dsp" path="../gitrepos/JUCE/modules"/>
 | 
				
			||||||
      </MODULEPATHS>
 | 
					      </MODULEPATHS>
 | 
				
			||||||
    </VS2017>
 | 
					    </VS2017>
 | 
				
			||||||
    <LINUX_MAKE targetFolder="Builds/LinuxMakefile" extraDefs="JUCE_WEB_BROWSER=0
">
 | 
					    <LINUX_MAKE targetFolder="Builds/LinuxMakefile" extraDefs="JUCE_WEB_BROWSER=0
"
 | 
				
			||||||
 | 
					                smallIcon="Yny1oQ" bigIcon="hG1CYd">
 | 
				
			||||||
      <CONFIGURATIONS>
 | 
					      <CONFIGURATIONS>
 | 
				
			||||||
        <CONFIGURATION name="Debug" isDebug="1" optimisation="1" linkTimeOptimisation="0"
 | 
					        <CONFIGURATION name="Debug" isDebug="1" optimisation="1" linkTimeOptimisation="0"
 | 
				
			||||||
                       targetName="PaulXStretch"/>
 | 
					                       targetName="PaulXStretch"/>
 | 
				
			||||||
@@ -156,7 +164,7 @@
 | 
				
			|||||||
      </MODULEPATHS>
 | 
					      </MODULEPATHS>
 | 
				
			||||||
    </LINUX_MAKE>
 | 
					    </LINUX_MAKE>
 | 
				
			||||||
    <VS2019 targetFolder="Builds/VisualStudio2019" externalLibraries="C:\ProgrammingProjects\fftw-3.3.6-pl2\fftw-3.3-libs\x64\Static-Release\libfftwf-3.3.lib"
 | 
					    <VS2019 targetFolder="Builds/VisualStudio2019" externalLibraries="C:\ProgrammingProjects\fftw-3.3.6-pl2\fftw-3.3-libs\x64\Static-Release\libfftwf-3.3.lib"
 | 
				
			||||||
            extraDefs="JUCE_MODAL_LOOPS_PERMITTED=1">
 | 
					            extraDefs="JUCE_MODAL_LOOPS_PERMITTED=1" smallIcon="Yny1oQ" bigIcon="hG1CYd">
 | 
				
			||||||
      <CONFIGURATIONS>
 | 
					      <CONFIGURATIONS>
 | 
				
			||||||
        <CONFIGURATION isDebug="1" name="Debug" headerPath="Source/PS_Source
Source/WDL
C:\ProgrammingProjects\gitrepos\JUCE\modules\vst2.x
"
 | 
					        <CONFIGURATION isDebug="1" name="Debug" headerPath="Source/PS_Source
Source/WDL
C:\ProgrammingProjects\gitrepos\JUCE\modules\vst2.x
"
 | 
				
			||||||
                       enablePluginBinaryCopyStep="1" vstBinaryLocation="C:\Program Files\VST_Plugins_x64"/>
 | 
					                       enablePluginBinaryCopyStep="1" vstBinaryLocation="C:\Program Files\VST_Plugins_x64"/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,14 @@
 | 
				
			|||||||
              headerPath="

" pluginFormats="buildAUv3,buildStandalone,enableIAA"
 | 
					              headerPath="

" pluginFormats="buildAUv3,buildStandalone,enableIAA"
 | 
				
			||||||
              jucerFormatVersion="1" useAppConfig="0" defines="JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1">
 | 
					              jucerFormatVersion="1" useAppConfig="0" defines="JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1">
 | 
				
			||||||
  <MAINGROUP id="nozXHl" name="PaulXStretch">
 | 
					  <MAINGROUP id="nozXHl" name="PaulXStretch">
 | 
				
			||||||
 | 
					    <GROUP id="{69E87EB6-7140-DB40-3383-82191582FEA1}" name="images">
 | 
				
			||||||
 | 
					      <FILE id="yM4pfJ" name="paulxstretch_icon_256.png" compile="0" resource="0"
 | 
				
			||||||
 | 
					            file="images/paulxstretch_icon_256.png"/>
 | 
				
			||||||
 | 
					      <FILE id="eZYcsl" name="paulxstretch_icon_1024.png" compile="0" resource="0"
 | 
				
			||||||
 | 
					            file="images/paulxstretch_icon_1024.png"/>
 | 
				
			||||||
 | 
					      <FILE id="OyhaIc" name="power.svg" compile="0" resource="1" file="images/power.svg"/>
 | 
				
			||||||
 | 
					      <FILE id="uMLkyi" name="power_sel.svg" compile="0" resource="1" file="images/power_sel.svg"/>
 | 
				
			||||||
 | 
					    </GROUP>
 | 
				
			||||||
    <GROUP id="{03DA6B32-F666-FF60-F168-4385D0847058}" name="Source">
 | 
					    <GROUP id="{03DA6B32-F666-FF60-F168-4385D0847058}" name="Source">
 | 
				
			||||||
      <GROUP id="{3B6D1AF9-E53E-2F78-24A5-D12A34009E6A}" name="PS_Source">
 | 
					      <GROUP id="{3B6D1AF9-E53E-2F78-24A5-D12A34009E6A}" name="PS_Source">
 | 
				
			||||||
        <FILE id="gDsFRp" name="globals.h" compile="0" resource="0" file="Source/PS_Source/globals.h"/>
 | 
					        <FILE id="gDsFRp" name="globals.h" compile="0" resource="0" file="Source/PS_Source/globals.h"/>
 | 
				
			||||||
@@ -55,8 +63,6 @@
 | 
				
			|||||||
            file="Source/PluginProcessor.cpp"/>
 | 
					            file="Source/PluginProcessor.cpp"/>
 | 
				
			||||||
      <FILE id="pt5tX8" name="PluginProcessor.h" compile="0" resource="0"
 | 
					      <FILE id="pt5tX8" name="PluginProcessor.h" compile="0" resource="0"
 | 
				
			||||||
            file="Source/PluginProcessor.h"/>
 | 
					            file="Source/PluginProcessor.h"/>
 | 
				
			||||||
      <FILE id="HtOPrw" name="power.svg" compile="0" resource="1" file="Source/power.svg"/>
 | 
					 | 
				
			||||||
      <FILE id="TY7Im1" name="power_sel.svg" compile="0" resource="1" file="Source/power_sel.svg"/>
 | 
					 | 
				
			||||||
      <FILE id="KcXfhC" name="ps3_BufferingAudioSource.cpp" compile="1" resource="0"
 | 
					      <FILE id="KcXfhC" name="ps3_BufferingAudioSource.cpp" compile="1" resource="0"
 | 
				
			||||||
            file="Source/ps3_BufferingAudioSource.cpp"/>
 | 
					            file="Source/ps3_BufferingAudioSource.cpp"/>
 | 
				
			||||||
      <FILE id="oWbh5E" name="ps3_BufferingAudioSource.h" compile="0" resource="0"
 | 
					      <FILE id="oWbh5E" name="ps3_BufferingAudioSource.h" compile="0" resource="0"
 | 
				
			||||||
@@ -73,7 +79,9 @@
 | 
				
			|||||||
                  iosBackgroundAudio="1" buildNumber="100" iosScreenOrientation="UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown"
 | 
					                  iosBackgroundAudio="1" buildNumber="100" iosScreenOrientation="UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown"
 | 
				
			||||||
                  iPadScreenOrientation="UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown"
 | 
					                  iPadScreenOrientation="UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown"
 | 
				
			||||||
                  UIStatusBarHidden="0" UIRequiresFullScreen="0" customPList="<plist version="1.0">
<dict>


<key>ITSAppUsesNonExemptEncryption</key>
	<false/>

<key>UIStatusBarHidden</key>
	<false/>
	<key>UIStatusBarStyle</key>
	<string>UIStatusBarStyleLightContent</string>

<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>


<key>NSLocalNetworkUsageDescription</key>
	<string>DrumJamPad uses networking to communicate with other local services</string>

<key>CFBundleDocumentTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeIconFiles</key>
			<array/>
			<key>CFBundleTypeName</key>
			<string>Audio File</string>
			<key>CFBundleTypeRole</key>
			<string>Viewer</string>
			<key>LSHandlerRank</key>
			<string>Owner</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>com.microsoft.waveform-audio</string>
				<string>public.aiff-audio</string>
				<string>com.apple.coreaudio-format</string>
				<string>public.mpeg-4-audio</string>
				<string>public.mp3</string>
			</array>
		</dict>
		</array>

</dict>
</plist>"
 | 
					                  UIStatusBarHidden="0" UIRequiresFullScreen="0" customPList="<plist version="1.0">
<dict>


<key>ITSAppUsesNonExemptEncryption</key>
	<false/>

<key>UIStatusBarHidden</key>
	<false/>
	<key>UIStatusBarStyle</key>
	<string>UIStatusBarStyleLightContent</string>

<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>


<key>NSLocalNetworkUsageDescription</key>
	<string>DrumJamPad uses networking to communicate with other local services</string>

<key>CFBundleDocumentTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeIconFiles</key>
			<array/>
			<key>CFBundleTypeName</key>
			<string>Audio File</string>
			<key>CFBundleTypeRole</key>
			<string>Viewer</string>
			<key>LSHandlerRank</key>
			<string>Owner</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>com.microsoft.waveform-audio</string>
				<string>public.aiff-audio</string>
				<string>com.apple.coreaudio-format</string>
				<string>public.mpeg-4-audio</string>
				<string>public.mp3</string>
			</array>
		</dict>
		</array>

</dict>
</plist>"
 | 
				
			||||||
                  UIFileSharingEnabled="1" UISupportsDocumentBrowser="1" extraDefs="PS_USE_VDSP_FFT=1">
 | 
					                  UIFileSharingEnabled="1" UISupportsDocumentBrowser="1" extraDefs="PS_USE_VDSP_FFT=1"
 | 
				
			||||||
 | 
					                  smallIcon="yM4pfJ" bigIcon="eZYcsl" iosBluetoothPermissionNeeded="1"
 | 
				
			||||||
 | 
					                  iosBackgroundBle="1">
 | 
				
			||||||
      <CONFIGURATIONS>
 | 
					      <CONFIGURATIONS>
 | 
				
			||||||
        <CONFIGURATION isDebug="1" name="Debug" headerPath="Source/PS_Source
Source/WDL
${HOME}/iosstatic/include"
 | 
					        <CONFIGURATION isDebug="1" name="Debug" headerPath="Source/PS_Source
Source/WDL
${HOME}/iosstatic/include"
 | 
				
			||||||
                       libraryPath="${HOME}/iosstatic/lib
"/>
 | 
					                       libraryPath="${HOME}/iosstatic/lib
"/>
 | 
				
			||||||
 
 | 
				
			|||||||