Merge branch 'master' into NSStoryboard_branch

This commit is contained in:
Gregory John Casamento 2020-03-20 05:20:28 -04:00
commit 6e40a3be19
42 changed files with 1878 additions and 353 deletions

2
.gitignore vendored
View file

@ -3,6 +3,7 @@ obj
*.sum
*.bundle
*.service
autom4te.cache
config.log
config.status
config.cache
@ -15,6 +16,7 @@ Source/config.h
Source/Info-gnustep.plist
Tests/gui/*/GNUmakefile
Tools/speech/GSSpeechServer.app
Tools/speech_recognizer/GSSpeechRecognitionServer.app
*~
# Created by https://www.gitignore.io/api/xcode

View file

@ -5,16 +5,16 @@ compiler:
- gcc
env:
- LIBRARY_COMBO=gnu-gnu-gnu
- LIBRARY_COMBO=ng-gnu-gnu
- LIBRARY_COMBO=ng-gnu-gnu BASE_ABI=--disable-mixedabi
- LIBRARY_COMBO=ng-gnu-gnu RUNTIME_VERSION=gnustep-1.9
- LIBRARY_COMBO=ng-gnu-gnu BASE_ABI=--disable-mixedabi RUNTIME_VERSION=gnustep-1.9
- LIBRARY_COMBO=ng-gnu-gnu RUNTIME_VERSION=gnustep-2.0
- LIBRARY_COMBO=ng-gnu-gnu BASE_ABI=--disable-mixedabi RUNTIME_VERSION=gnustep-2.0
matrix:
exclude:
- compiler: gcc
env: LIBRARY_COMBO=ng-gnu-gnu
env: LIBRARY_COMBO=ng-gnu-gnu RUNTIME_VERSION=gnustep-1.9
- compiler: gcc
env: LIBRARY_COMBO=ng-gnu-gnu BASE_ABI=--disable-mixedabi
env: LIBRARY_COMBO=ng-gnu-gnu BASE_ABI=--disable-mixedabi RUNTIME_VERSION=gnustep-1.9
- compiler: gcc
env: LIBRARY_COMBO=ng-gnu-gnu RUNTIME_VERSION=gnustep-2.0
- compiler: gcc

102
ChangeLog
View file

@ -1,3 +1,105 @@
2020-03-12 Sergii Stoian <stoyan255@gmail.com>
* Model/GNUmakefile: do not overwrite ADDITIONAL_INCLUDE_DIRS
value to help RPM build. In spec file ADDITIONAL_INCLUDE_DIRS can be sat
to subdirectories which are create by RPM build tool.
2020-03-05 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m (_applyFrame:): new helper method to do actual
resizing.
(setFrame:display:): use _applyFrame method.
(applicationDidChangeScreenParameters:): Use _applyFrame: because our
origin in OpenStep coordinates might be unchanged and `setFrame:display:`
has check for it.
2020-02-28 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m (center): always center window on main screen -
monitor where user expects to see window.
2020-02-26 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m (sendEvent:): removed usage of extra local variables
in GSAppKitWindowMoved code block.
2020-02-23 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m
(applicationDidChangeScreenParameters:): quit while loop after
screen was found.
(sendEvent:): use `_screen` ivar to get screen befor frame change.
* Source/NSMenu.m (windowDidChangeScreen:): join two if statements.
2020-02-23 Fred Kiefer <FredKiefer@gmx.de>
* Headers/Additions/GNUstepGUI/GSXibLoading.h,
* Source/GSXib5KeyedUnarchiver.m,
* Source/GSXibLoading.m: Move more behaviour from the
IBActionConnection5 and IBOutletConnection5 classes
to the original ones.
2020-02-23 Fred Kiefer <FredKiefer@gmx.de>
* .travis.yml
* travis-deps.sh: Try to keep up with Niels' changes in base.
2020-02-20 Sergii Stoian <stoyan255@gmail.com>
* Source/NSMenu.m (_setGeometry): take into account main screen
origin when calculating horizontal menu postion.
* Source/NSApplication.m (_appIconInit): take into account main screen
origin when placing application icon.
2020-02-13 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m (setFrame:display:): use _screeForFrame: here
to prevent `_screen` reassign - it will be reassigned in
sendEvent: (GSAppKitWindowMoved event) after call to [self screen].
(setFrameFromString:): removed unused code because _screenForFrame:
never returns `nil`. Do not reassign `_screen` here.
2020-02-12 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m (sendEvent:): set current screen to ivar and
send WindowDidChangeScreen notification if window was moved to other
screen.
* Source/NSScreen.m (mainScreen): returns screen of main menu if no
key window exists. With this implementation default screen (screen at
index 0 in screens array) should never be returned.
* Source/NSMenu.m (initWithTitle:): observe WindowDidBecomeKey and
WindowDidChangeScreen notifications.
(windowDidChangeScreen:): new method to handle observed notification
added above. Moves menu to screen of key window for both cases: when
key window moved to or activated on different screen.
2020-02-09 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSFontDescriptor.m: Correct key for encoding and decoding.
2020-01-31 Sergii Stoian <stoyan255@gmail.com>
* Source/GSTitleView.m (mouseDown:): limit menu movement to screen
frame for top/left/right edges. Menu can be moved to the bottom until
title is completely visible.
2020-01-27 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m (applicationDidChangeScreenParameters): take into
account screen origin change during window position recalculation.
2020-01-26 Sergii Stoian <stoyan255@gmail.com>
* Source/NSWindow.m (initWithContentRect:styleMask:backing:defer:):
added observer of NSApplicationDidChangeScreenParametersNotification.
(applicationDidChangeScreenParameters:): callback for added notification -
updates window position, set new screen object and saves frame if
autosave name exists.
2020-01-23 Fred Kiefer <FredKiefer@gmx.de>
* Source/GSXib5KeyedUnarchiver.m: Remove NSWindowTemplate5.

View file

@ -178,6 +178,15 @@
is meant to make things friendlier for slow computers.
</p>
</desc>
<term>GSScaleFactor</term>
<desc>
<p>
A floating point number, <code>1.0</code> by default. Scales
GUI elements by the given factor for high-DPI monitors. DPI
auto-detection on some platforms (only Windows, for now) will
cause the default to appear to change.
</p>
</desc>
<term>GSUnknownFileTool</term>
<desc>
<p>

View file

@ -86,6 +86,7 @@
@interface IBActionConnection: IBConnection
{
NSString *trigger;
}
@end

View file

@ -18,6 +18,9 @@
/* Define to 1 if you have the <flite/flite.h> header file. */
#undef HAVE_FLITE_FLITE_H
/* Define to 1 if you have the pocketsphinx.h header file */
#undef HAVE_POCKETSPHINX_POCKETSPHINX_EXPORT_H
/* Define to 1 if you have the `floorf' function. */
#undef HAVE_FLOORF

View file

@ -141,6 +141,7 @@
#import <AppKit/NSArrayController.h>
#import <AppKit/NSBezierPath.h>
#import <AppKit/NSButtonTouchBarItem.h>
#import <AppKit/NSColorSampler.h>
#import <AppKit/NSColorSpace.h>
#import <AppKit/NSComboBox.h>
#import <AppKit/NSComboBoxCell.h>

View file

@ -0,0 +1,53 @@
/* Definition of class NSColorSampler
Copyright (C) 2020 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: Thu Mar 12 03:11:27 EDT 2020
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#ifndef _NSColorSampler_h_GNUSTEP_GUI_INCLUDE
#define _NSColorSampler_h_GNUSTEP_GUI_INCLUDE
#import <Foundation/NSObject.h>
#if OS_API_VERSION(MAC_OS_X_VERSION_10_0, GS_API_LATEST)
#if defined(__cplusplus)
extern "C" {
#endif
@class NSColor;
DEFINE_BLOCK_TYPE(GSColorSampleHandler, void, NSColor*);
@interface NSColorSampler : NSObject
- (void) showSamplerWithSelectionHandler: (GSColorSampleHandler)selectionHandler;
@end
#if defined(__cplusplus)
}
#endif
#endif /* GS_API_MACOSX */
#endif /* _NSColorSampler_h_GNUSTEP_GUI_INCLUDE */

View file

@ -8,16 +8,16 @@
* This file is part of GNUstep.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110
* USA.

View file

@ -8,16 +8,16 @@
* This file is part of GNUstep.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110
* USA.

View file

@ -26,6 +26,7 @@
#define _NSSpeechRecognizer_h_GNUSTEP_GUI_INCLUDE
#import <Foundation/NSObject.h>
#import <AppKit/AppKitDefines.h>
#if OS_API_VERSION(MAC_OS_X_VERSION_10_0, GS_API_LATEST)
@ -33,10 +34,55 @@
extern "C" {
#endif
@interface NSSpeechRecognizer : NSObject
@protocol NSSpeechRecognizerDelegate;
@class NSArray, NSString, NSUUID;
@interface NSSpeechRecognizer : NSObject
{
id<NSSpeechRecognizerDelegate> _delegate;
NSArray *_commands;
NSString *_displayCommandsTitle;
NSUUID *_uuid;
BOOL _blocksOtherRecognizers;
BOOL _listensInForegroundOnly;
BOOL _appInForeground; // private
BOOL _isListening;
}
// Initialize
- (instancetype) init;
- (id<NSSpeechRecognizerDelegate>) delegate;
- (void) setDelegate: (id<NSSpeechRecognizerDelegate>) delegate;
// Configuring...
- (NSArray *) commands;
- (void) setCommands: (NSArray *)commands;
- (NSString *) displayCommandsTitle;
- (void) setDisplayCommandsTitle: (NSString *)displayCommandsTitle;
- (BOOL) listensInForegroundOnly;
- (void) setListensInForegroundOnly: (BOOL)listensInForegroundOnly;
- (BOOL) blocksOtherRecognizers;
- (void) setBlocksOtherRecognizers: (BOOL)blocksOtherRecognizers;
// Listening
- (void) startListening;
- (void) stopListening;
@end
// Protocol
@protocol NSSpeechRecognizerDelegate
- (void) speechRecognizer: (NSSpeechRecognizer *)sender
didRecognizeCommand: (NSString *)command;
@end
APPKIT_EXPORT NSString *GSSpeechRecognizerDidRecognizeWordNotification;
#if defined(__cplusplus)
}
#endif

View file

@ -36,7 +36,7 @@ typedef enum
NSSpeechImmediateBoundary = 0,
NSSpeechWordBoundary,
NSSpeechSentenceBoundary
}
}
NSSpeechBoundary;
// forward declarations...
@ -184,3 +184,4 @@ extern NSString *NSSpeechDictionaryEntryPhonemes;
@end
#endif // _GNUstep_H_NSSpeechSynthesizer

View file

@ -12,7 +12,6 @@ MISSING HEADERS
> NSCollectionViewGridLayout.h
> NSCollectionViewLayout.h
> NSCollectionViewTransitionLayout.h
> NSColorSampler.h
> NSDictionaryController.h
> NSDiffableDataSource.h
> NSDraggingItem.h
@ -40,7 +39,6 @@ MISSING HEADERS
> NSPressureConfiguration.h
> NSSharingServicePickerToolbarItem.h
> NSSliderAccessory.h
> NSSpeechRecognizer.h
> NSSplitViewController.h
> NSSplitViewItem.h
> NSStackView.h
@ -76,6 +74,8 @@ Completed
> NSDataAsset.h
> NSTouch.h
> NSTouchBar.h
> NSSpeechRecognizer.h
> NSColorSampler.h
Obsolete
---

View file

@ -66,9 +66,9 @@ ADDITIONAL_CPPFLAGS += $(RUNTIME_DEFINE) $(GUI_DEFINE) $(BACKEND_DEFINE)
ADDITIONAL_LIB_DIRS += -L$(GNUSTEP_OBJ_DIR)
ifeq ($(GUI_LIB), gnu)
ADDITIONAL_LIB_DIRS += -L../Source/$(GNUSTEP_OBJ_DIR)
ADDITIONAL_INCLUDE_DIRS = -I../Headers/Additions -I../Headers
ADDITIONAL_INCLUDE_DIRS += -I../Headers/Additions -I../Headers
else
ADDITIONAL_INCLUDE_DIRS = -I../Headers/Additions
ADDITIONAL_INCLUDE_DIRS += -I../Headers/Additions
endif
ADDITIONAL_OBJC_FLAGS += $(BACKEND_DEFINE)

View file

@ -2,7 +2,7 @@
Copyright (C) 2003 Free Software Foundation, Inc.
Author: Serg Stoyan <stoyan@on.com.ua>
Author: Sergii Stoian <stoyan255@gmail.com>
Date: Mar 2003
This file is part of the GNUstep GUI Library.
@ -41,6 +41,7 @@
#import "AppKit/NSStringDrawing.h"
#import "AppKit/NSView.h"
#import "AppKit/NSWindow.h"
#import "AppKit/NSScreen.h"
#import "GNUstepGUI/GSTitleView.h"
#import "GNUstepGUI/GSTheme.h"
@ -238,9 +239,32 @@
NSDate *theDistantFuture = [NSDate distantFuture];
NSPoint startWindowOrigin;
NSPoint endWindowOrigin;
NSRect screenFrame = NSZeroRect;
CGFloat leftLimit = -1.0;
CGFloat topLimit = -1.0 ;
CGFloat rightLimit = -1.0;
CGFloat bottomLimit = 0.0;
NSDebugLLog (@"NSMenu", @"Mouse down in title!");
// Define move constrains for menu
if (_ownedByMenu)
{
NSRect windowFrame;
NSScreen *screen;
if (_window && (screen = [_window screen]))
{
windowFrame = [_window frame];
screenFrame = [screen frame];
leftLimit = screenFrame.origin.x;
topLimit = NSMaxY(screenFrame) - windowFrame.size.height;
rightLimit = NSMaxX(screenFrame) - windowFrame.size.width;
bottomLimit = screenFrame.origin.y -
(windowFrame.size.height - [self frame].size.height);
}
}
// Remember start position of window
startWindowOrigin = [_window frame].origin;
@ -275,6 +299,19 @@
origin.y += (location.y - lastLocation.y);
if (_ownedByMenu)
{
if (screenFrame.size.width > 0 && screenFrame.size.height > 0)
{
if (origin.x <= leftLimit)
origin.x = leftLimit;
else if (origin.x >= rightLimit)
origin.x = rightLimit;
if (origin.y >= topLimit)
origin.y = topLimit;
else if (origin.y <= bottomLimit)
origin.y = bottomLimit;
}
[_owner nestedSetFrameOrigin: origin];
}
else

View file

@ -113,118 +113,6 @@ static NSString *ApplicationClass = nil;
@end
@interface IBActionConnection5 : IBActionConnection
{
NSString *trigger;
}
@end
@implementation IBActionConnection5
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super initWithCoder: coder];
if (self)
{
trigger = nil;
if ([coder allowsKeyedCoding])
{
// label and source string tags have changed for XIB5...
ASSIGN(label, [coder decodeObjectForKey: @"selector"]);
ASSIGN(source, [coder decodeObjectForKey: @"target"]);
// destination string tag is still the same (so far) and loaded
// by base class...
//ASSIGN(destination, [coder decodeObjectForKey: @"destination"]);
// Looks like the 'trigger' attribute should be used to override the
// target/action setup method...
if ([coder containsValueForKey: @"trigger"])
ASSIGN(trigger, [coder decodeObjectForKey: @"trigger"]);
}
else
{
[NSException raise: NSInvalidArgumentException
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
NSStringFromClass([coder class])];
}
}
return self;
}
- (NSString*) trigger
{
return trigger;
}
- (void) establishConnection
{
if (trigger && [trigger length])
{
SEL sel = NSSelectorFromString(label);
NSString *selName = [NSString stringWithFormat: @"set%@%@:",
[[trigger substringToIndex: 1] uppercaseString],
[trigger substringFromIndex: 1]];
SEL trigsel = NSSelectorFromString(selName);
if (sel && trigsel && [destination respondsToSelector: trigsel])
{
NSWarnMLog(@"setting trigger %@ to selector %@", selName, label);
//[destination setTarget: source]; // Not needed???
[destination performSelector: trigsel withObject: (id)sel];
}
else if (!sel)
{
NSWarnMLog(@"label %@ does not correspond to any selector", label);
}
else if (!trigsel)
{
NSWarnMLog(@"trigger %@ does not correspond to any selector", trigger);
}
else
{
NSWarnMLog(@"destination class (%@) does not respond to trigger selector %@",
NSStringFromClass([destination class]), selName);
}
// PREMATURE RETURN...
return;
}
// Otherwise invoke the super class' method...
[super establishConnection];
}
@end
@interface IBOutletConnection5 : IBOutletConnection
@end
@implementation IBOutletConnection5
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super initWithCoder: coder];
if (self)
{
if ([coder allowsKeyedCoding])
{
// label string tag has changed for XIB5...
ASSIGN(label, [coder decodeObjectForKey: @"property"]);
// destination and source string tags are still the same (so far) and loaded
// by base class...
}
else
{
[NSException raise: NSInvalidArgumentException
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
NSStringFromClass([coder class])];
}
}
return self;
}
@end
@interface IBUserDefinedRuntimeAttribute5 : IBUserDefinedRuntimeAttribute
@end
@ -313,8 +201,8 @@ static NSArray *XmlBoolDefaultYes = nil;
@"NSSegmentItem", @"segment",
@"NSCell", @"customCell",
@"NSCustomObject5", @"customObject",
@"IBOutletConnection5", @"outlet",
@"IBActionConnection5", @"action",
@"IBOutletConnection", @"outlet",
@"IBActionConnection", @"action",
@"NSNibBindingConnector", @"binding",
@"NSWindowTemplate", @"window",
@"NSView", @"tableCellView",
@ -2401,7 +2289,8 @@ didStartElement: (NSString*)elementName
mask.flags.highlighted = [[attributes objectForKey: @"highlighted"] boolValue];
mask.flags.disabled = ([attributes objectForKey: @"enabled"] ?
[[attributes objectForKey: @"enabled"] boolValue] == NO : NO);
mask.flags.editable = [[attributes objectForKey: @"editable"] boolValue];
mask.flags.editable = ([attributes objectForKey: @"editable"] ?
[[attributes objectForKey: @"editable"] boolValue] : YES);
mask.flags.vCentered = [[attributes objectForKey: @"alignment"] isEqualToString: @"center"];
mask.flags.hCentered = [[attributes objectForKey: @"alignment"] isEqualToString: @"center"];
mask.flags.bordered = [[borderStyle lowercaseString] containsString: @"border"];
@ -3121,7 +3010,7 @@ didStartElement: (NSString*)elementName
return flag;
}
- (NSPoint) decodePointForKey:(NSString *)key
- (NSPoint) decodePointForKey: (NSString *)key
{
NSPoint point = NSZeroPoint;

View file

@ -421,18 +421,117 @@
@implementation IBActionConnection
- (void) dealloc
{
DESTROY(trigger);
[super dealloc];
}
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super initWithCoder: coder];
if (self)
{
if ([coder allowsKeyedCoding])
{
// label and source string tags have changed for XIB5...
if ([coder containsValueForKey: @"selector"])
{
ASSIGN(label, [coder decodeObjectForKey: @"selector"]);
}
if ([coder containsValueForKey: @"target"])
{
ASSIGN(source, [coder decodeObjectForKey: @"target"]);
}
// Looks like the 'trigger' attribute should be used to override the
// action setup method...
if ([coder containsValueForKey: @"trigger"])
{
ASSIGN(trigger, [coder decodeObjectForKey: @"trigger"]);
}
}
else
{
[NSException raise: NSInvalidArgumentException
format: @"Can't decode %@ with %@.", NSStringFromClass([self class]),
NSStringFromClass([coder class])];
}
}
return self;
}
- (NSString*) trigger
{
return trigger;
}
- (void) establishConnection
{
SEL sel = NSSelectorFromString(label);
[destination setTarget: source];
[destination setAction: sel];
if (trigger && [trigger length])
{
NSString *selName = [NSString stringWithFormat: @"set%@%@:",
[[trigger substringToIndex: 1] uppercaseString],
[trigger substringFromIndex: 1]];
SEL trigsel = NSSelectorFromString(selName);
if (sel && trigsel && [destination respondsToSelector: trigsel])
{
NSWarnMLog(@"setting trigger %@ to selector %@", selName, label);
[destination performSelector: trigsel withObject: (id)sel];
}
else if (!sel)
{
NSWarnMLog(@"label %@ does not correspond to any selector", label);
}
else if (!trigsel)
{
NSWarnMLog(@"trigger %@ does not correspond to any selector", trigger);
}
else
{
NSWarnMLog(@"destination class (%@) does not respond to trigger selector %@",
NSStringFromClass([destination class]), selName);
}
}
else
{
// Otherwise invoke the normal method...
[destination setAction: sel];
}
}
@end
@implementation IBOutletConnection
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super initWithCoder: coder];
if (self)
{
if ([coder allowsKeyedCoding])
{
// label string tag has changed for XIB5...
if ([coder containsValueForKey: @"property"])
{
ASSIGN(label, [coder decodeObjectForKey: @"property"]);
}
}
else
{
[NSException raise: NSInvalidArgumentException
format: @"Can't decode %@ with %@.", NSStringFromClass([self class]),
NSStringFromClass([coder class])];
}
}
return self;
}
- (void) establishConnection
{
NS_DURING
@ -866,10 +965,10 @@
- (NSString*) description
{
return [NSString stringWithFormat:
@"%@ - sourceID: %@: maxID: %@: objectRecords: %@: flattenedProperties: %@: connectionRecords: %@: ",
[super description], sourceID, maxID, objectRecords,
flattenedProperties, connectionRecords];
return [NSString stringWithFormat: @"%@ - sourceID: %@: maxID: %d:"
@" objectRecords: %@: flattenedProperties: %@: connectionRecords: %@: ",
[super description], sourceID, maxID,
objectRecords, flattenedProperties, connectionRecords];
}
- (NSEnumerator*) connectionRecordEnumerator

View file

@ -3896,6 +3896,7 @@ struct _DelegateWrapper
iconContentRect = GSGetIconFrame(_app_icon_window);
iconFrame = [_app_icon_window frameRectForContentRect: iconContentRect];
iconFrame.origin = [[NSScreen mainScreen] frame].origin;
iconViewFrame = NSMakeRect(0, 0,
iconContentRect.size.width, iconContentRect.size.height);
[_app_icon_window setFrame: iconFrame display: YES];

158
Source/NSColorSampler.m Normal file
View file

@ -0,0 +1,158 @@
/* Implementation of class NSColorSampler
Copyright (C) 2019 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: Thu Mar 12 03:11:27 EDT 2020
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import <Foundation/NSGeometry.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSException.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSLock.h>
#import <AppKit/NSApplication.h>
#import <AppKit/NSBitmapImageRep.h>
#import <AppKit/NSColorSampler.h>
#import <AppKit/NSCursor.h>
#import <AppKit/NSColor.h>
#import <AppKit/NSEvent.h>
#import <AppKit/NSImage.h>
#import <AppKit/NSScreen.h>
#import <AppKit/NSPanel.h>
#import <GNUstepGUI/GSDisplayServer.h>
static NSLock *_gs_gui_color_sampler_lock = nil;
static NSColorSampler *_gs_gui_color_sampler = nil;
@interface NSWindow (private)
- (void) _captureMouse: sender;
- (void) _releaseMouse: sender;
@end
@implementation NSColorSampler
+ (void) initialize
{
if (self == [NSColorSampler class])
{
// Initial version
[self setVersion: 1];
_gs_gui_color_sampler_lock = [NSLock new];
}
}
- (instancetype) init
{
if (_gs_gui_color_sampler == nil)
{
_gs_gui_color_sampler = self;
}
if (self != _gs_gui_color_sampler)
{
RELEASE(self);
return _gs_gui_color_sampler;
}
return self;
}
- (void) showSamplerWithSelectionHandler: (GSColorSampleHandler)selectionHandler
{
NSEvent *currentEvent;
NSCursor *cursor;
NSRect contentRect = NSMakeRect(-1024,-1024,0,0);
unsigned int style = NSTitledWindowMask | NSClosableWindowMask
| NSResizableWindowMask | NSUtilityWindowMask;
NSPanel *w = nil;
NSColor *color = nil;
[_gs_gui_color_sampler_lock lock];
w = [[NSPanel alloc] initWithContentRect: contentRect
styleMask: style
backing: NSBackingStoreRetained
defer: NO
screen: nil];
[w setBecomesKeyOnlyIfNeeded: YES];
[w makeKeyAndOrderFront: self];
[w _captureMouse: self];
/**
* There was code here to dynamically generate a magnifying glass
* cursor with a magnified portion of the screenshot in it,
* but changing the cursor rapidly on X seems to cause flicker,
* so we just use a plain magnifying glass. (dynamic code is in r33543)
*/
cursor = [[NSCursor alloc] initWithImage: [NSImage imageNamed: @"MagnifyGlass"]
hotSpot: NSMakePoint(12, 13)];
AUTORELEASE(cursor);
[cursor push];
NS_DURING
{
do
{
NSPoint mouseLoc;
NSImage *img;
CREATE_AUTORELEASE_POOL(pool);
RELEASE(color);
currentEvent = [NSApp nextEventMatchingMask: NSLeftMouseDownMask | NSLeftMouseUpMask | NSMouseMovedMask
untilDate: [NSDate distantFuture]
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
mouseLoc = [w convertBaseToScreen: [w mouseLocationOutsideOfEventStream]];
img = [GSCurrentServer() contentsOfScreen: [[w screen] screenNumber]
inRect: NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)];
if (nil != img)
{
NSBitmapImageRep *rep = (NSBitmapImageRep *)[img bestRepresentationForDevice: nil];
color = [rep colorAtX: 0 y: 0];
RETAIN(color);
}
[pool drain];
} while ([currentEvent type] != NSLeftMouseUp &&
[currentEvent type] != NSLeftMouseDown);
}
NS_HANDLER
{
NSLog(@"Exception occurred in -[NSColorSampler showSamplerWithSelectionHandler:] : %@",
localException);
}
NS_ENDHANDLER;
CALL_BLOCK(selectionHandler, color);
RELEASE(color);
[NSCursor pop];
[w _releaseMouse: self];
[w close];
[_gs_gui_color_sampler_lock unlock];
}
@end

View file

@ -155,7 +155,7 @@
{
if ([aCoder allowsKeyedCoding])
{
[aCoder encodeObject: _attributes forKey: @"NSAttributes"];
[aCoder encodeObject: _attributes forKey: @"NSFontDescriptorAttributes"];
}
else
{
@ -167,7 +167,7 @@
{
if ([aDecoder allowsKeyedCoding])
{
_attributes = RETAIN([aDecoder decodeObjectForKey: @"NSAttributes"]);
_attributes = RETAIN([aDecoder decodeObjectForKey: @"NSFontDescriptorAttributes"]);
}
else
{

View file

@ -470,8 +470,10 @@ static BOOL menuBarVisible = YES;
if (_menu.horizontal == YES)
{
origin = NSMakePoint (0, [[NSScreen mainScreen] frame].size.height
- [_aWindow frame].size.height);
NSRect screenFrame = [[NSScreen mainScreen] frame];
origin = NSMakePoint (0, screenFrame.size.height
- [_aWindow frame].size.height);
origin.y += screenFrame.origin.y;
[_aWindow setFrameOrigin: origin];
[_bWindow setFrameOrigin: origin];
}
@ -1801,6 +1803,23 @@ static BOOL menuBarVisible = YES;
[[supermenu menuRepresentation] setHighlightedItemIndex: -1];
supermenu->_attachedMenu = nil;
}
[nc addObserver: self
selector: @selector(windowDidChangeScreen:)
name: NSWindowDidBecomeKeyNotification
object: nil];
[nc addObserver: self
selector: @selector(windowDidChangeScreen:)
name: NSWindowDidChangeScreenNotification
object: nil];
}
else
{
[nc removeObserver: self
name: NSWindowDidBecomeKeyNotification
object: nil];
[nc removeObserver: self
name: NSWindowDidChangeScreenNotification
object: nil];
}
[_view update];
}
@ -1848,6 +1867,18 @@ static BOOL menuBarVisible = YES;
[[GSTheme theme] updateAllWindowsWithMenu: [NSApp mainMenu]];
}
[self _showTornOffMenuIfAny: notification];
if ([NSApp mainMenu] == self)
{
[nc addObserver: self
selector: @selector(windowDidChangeScreen:)
name: NSWindowDidBecomeKeyNotification
object: nil];
[nc addObserver: self
selector: @selector(windowDidChangeScreen:)
name: NSWindowDidChangeScreenNotification
object: nil];
}
}
- (void) _showOnActivateApp: (NSNotification*)notification
@ -1860,6 +1891,38 @@ static BOOL menuBarVisible = YES;
}
}
- (void) windowDidChangeScreen: (NSNotification*)notification
{
NSWindow *window = [notification object];
NSRect frame;
NSRect oldScreenFrame;
NSRect newScreenFrame;
CGFloat yOffset;
if ([window isKindOfClass: [NSPanel class]]
|| window == _aWindow
|| [window isKeyWindow] == NO
|| [_aWindow screen] == [window screen]
|| [_aWindow isVisible] == NO)
{
return;
}
oldScreenFrame = [[_aWindow screen] frame];
newScreenFrame = [[window screen] frame];
frame = [_aWindow frame];
// Keep left offset fixed
frame.origin.x += newScreenFrame.origin.x - oldScreenFrame.origin.x;
// Keep top offset fixed
yOffset = NSMaxY(oldScreenFrame) - NSMaxY(frame);
frame.origin.y = NSMaxY(newScreenFrame) - yOffset - frame.size.height;
// setFrame: changes _screen value.
[self nestedSetFrameOrigin: frame.origin];
}
- (BOOL) isTransient
{
return _menu.transient;

View file

@ -60,12 +60,7 @@
if (self == [NSScreen class])
{
[self setVersion: 1];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_resetScreens:)
name: NSApplicationDidChangeScreenParametersNotification
object: nil];
}
}
}
static NSMutableArray *screenArray = nil;
@ -73,11 +68,6 @@ static NSMutableArray *screenArray = nil;
/**
* Resets the cached list of screens.
*/
+ (void) _resetScreens: (NSNotification*)notification
{
[self resetScreens];
}
+ (void) resetScreens
{
DESTROY(screenArray);
@ -132,6 +122,11 @@ static NSMutableArray *screenArray = nil;
NSWindow *keyWindow;
keyWindow = [NSApp keyWindow];
if (keyWindow == nil)
{
keyWindow = [[NSApp mainMenu] window];
}
if (keyWindow != nil)
{
return [keyWindow screen];

View file

@ -8,16 +8,16 @@
* This file is part of GNUstep.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110
* USA.

View file

@ -8,16 +8,16 @@
* This file is part of GNUstep.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the Lesser GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the Lesser GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110
* USA.

View file

@ -23,8 +23,313 @@
*/
#import <AppKit/NSSpeechRecognizer.h>
#import <AppKit/NSApplication.h>
#import <Foundation/NSDistantObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSThread.h>
#import <Foundation/NSError.h>
#import <Foundation/NSConnection.h>
#import <Foundation/NSDistributedNotificationCenter.h>
#import <Foundation/NSDebug.h>
#import <Foundation/NSUUID.h>
#import "GSFastEnumeration.h"
#import "AppKit/NSWorkspace.h"
#import "AppKit/NSWindow.h"
@implementation NSSpeechRecognizer
id _speechRecognitionServer = nil;
BOOL _serverLaunchTested = NO;
#define SPEECH_RECOGNITION_SERVER @"GSSpeechRecognitionServer"
@interface NSObject (SpeechRecognitionServerPrivate)
- (void) addToBlockingRecognizers: (NSString *)s;
- (void) removeFromBlockingRecognizers: (NSString *)s;
- (BOOL) isBlocking: (NSString *)s;
- (void) addClient;
@end
@implementation NSSpeechRecognizer
+ (void) initialize
{
if (self == [NSSpeechRecognizer class])
{
// Test for an existant server...
_speechRecognitionServer =
[NSConnection rootProxyForConnectionWithRegisteredName: SPEECH_RECOGNITION_SERVER
host: nil];
// if none exists, start one. We will connect with it in init.
if (nil == _speechRecognitionServer)
{
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws launchApplication: SPEECH_RECOGNITION_SERVER
showIcon: NO
autolaunch: NO];
}
}
}
- (void) _restartServer
{
if (nil == _speechRecognitionServer && !_serverLaunchTested)
{
unsigned int i = 0;
// Wait for up to five seconds for the server to launch, then give up.
for (i = 0 ; i < 50 ; i++)
{
_speechRecognitionServer = [NSConnection
rootProxyForConnectionWithRegisteredName: SPEECH_RECOGNITION_SERVER
host: nil];
RETAIN(_speechRecognitionServer);
if (nil != _speechRecognitionServer)
{
NSDebugLog(@"Server found!!!");
break;
}
else
{
NS_DURING
{
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws launchApplication: SPEECH_RECOGNITION_SERVER
showIcon: NO
autolaunch: NO];
}
NS_HANDLER
{
}
NS_ENDHANDLER;
}
[NSThread sleepForTimeInterval: 0.1];
}
// Set a flag so we don't bother waiting for the speech recognition server to
// launch the next time if it didn't work this time.
_serverLaunchTested = YES;
}
if (_speechRecognitionServer == nil)
{
NSLog(@"Cannot restart speech recognition server.");
}
}
- (void) processNotification: (NSNotification *)note
{
NSString *word = (NSString *)[note object];
NSDebugLog(@"Notified");
if (_listensInForegroundOnly)
{
if (_appInForeground == NO)
{
NSDebugLog(@"Only in foreground..");
return;
}
}
if (_blocksOtherRecognizers)
{
NS_DURING
{
/*
if ([_speechRecognitionServer isBlocking: [_uuid UUIDString]] == NO)
{
// If we are not a blocking recognizer, then we are blocked...
NSDebugLog(@"Blocked...");
return;
}
*/
}
NS_HANDLER
{
NSLog(@"%@", localException);
[self _restartServer];
}
NS_ENDHANDLER;
}
word = [word lowercaseString];
FOR_IN(NSString*, obj, _commands)
{
if ([[obj lowercaseString] isEqualToString: word])
{
[_delegate speechRecognizer: self
didRecognizeCommand: word];
}
}
END_FOR_IN(_commands);
}
- (void) processAppStatusNotification: (NSNotification *)note
{
NSString *name = [note name];
if ([name isEqualToString: NSApplicationDidBecomeActiveNotification] ||
[name isEqualToString: NSApplicationDidFinishLaunchingNotification] ||
[name isEqualToString: NSWindowDidBecomeKeyNotification])
{
_appInForeground = YES;
}
else
{
_appInForeground = NO;
}
}
// Initialize
- (instancetype) init
{
self = [super init];
if (self != nil)
{
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(processAppStatusNotification:)
name: NSApplicationDidFinishLaunchingNotification
object: nil];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(processAppStatusNotification:)
name: NSWindowDidBecomeKeyNotification
object: nil];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(processAppStatusNotification:)
name: NSApplicationDidBecomeActiveNotification
object: nil];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(processAppStatusNotification:)
name: NSApplicationDidResignActiveNotification
object: nil];
_delegate = nil;
_blocksOtherRecognizers = NO;
_listensInForegroundOnly = YES;
_appInForeground = YES;
_uuid = [NSUUID UUID];
[self _restartServer];
}
NS_DURING
{
[_speechRecognitionServer addClient]; // do this to update the client count;
}
NS_HANDLER
{
NSLog(@"%@", localException);
[self _restartServer];
}
NS_ENDHANDLER;
return self;
}
- (void) dealloc
{
[[NSDistributedNotificationCenter defaultCenter] removeObserver: self];
[[NSNotificationCenter defaultCenter] removeObserver: self];
_delegate = nil;
[super dealloc];
}
// Delegate
- (id<NSSpeechRecognizerDelegate>) delegate
{
return _delegate;
}
- (void) setDelegate: (id<NSSpeechRecognizerDelegate>)delegate
{
_delegate = delegate;
}
// Configuring...
- (NSArray *) commands
{
return _commands;
}
- (void) setCommands: (NSArray *)commands
{
ASSIGNCOPY(_commands, commands);
}
- (NSString *) displayCommandsTitle
{
return _displayCommandsTitle;
}
- (void) setDisplayCommandsTitle: (NSString *)displayCommandsTitle
{
ASSIGNCOPY(_displayCommandsTitle, displayCommandsTitle);
}
- (BOOL) listensInForegroundOnly
{
return _listensInForegroundOnly;
}
- (void) setListensInForegroundOnly: (BOOL)listensInForegroundOnly
{
_listensInForegroundOnly = listensInForegroundOnly;
}
- (BOOL) blocksOtherRecognizers
{
return _blocksOtherRecognizers;
}
- (void) setBlocksOtherRecognizers: (BOOL)blocksOtherRecognizers
{
NS_DURING
{
if (blocksOtherRecognizers == YES)
{
[_speechRecognitionServer addToBlockingRecognizers: [_uuid UUIDString]];
}
else
{
[_speechRecognitionServer removeFromBlockingRecognizers: [_uuid UUIDString]];
}
_blocksOtherRecognizers = blocksOtherRecognizers;
}
NS_HANDLER
{
NSLog(@"%@", localException);
[self _restartServer];
}
NS_ENDHANDLER;
}
// Listening
- (void) startListening
{
// Start listening to the notification being sent by the server....
[[NSDistributedNotificationCenter defaultCenter]
addObserver: self
selector: @selector(processNotification:)
name: GSSpeechRecognizerDidRecognizeWordNotification
object: nil];
}
- (void) stopListening
{
// Remove the observer for the notification....
[[NSDistributedNotificationCenter defaultCenter]
removeObserver: self
name: GSSpeechRecognizerDidRecognizeWordNotification
object: nil];
}
@end

View file

@ -102,58 +102,60 @@ static Class NSSpeechSynthesizerClass;
- (NSSpeechSynthesizer*)newSynthesizer;
@end
@implementation NSSpeechSynthesizer
@implementation NSSpeechSynthesizer
- (id) initWithVoice: (NSString *)voice
{
return self;
}
+ (void)initialize
{
NSSpeechSynthesizerClass = [NSSpeechSynthesizer class];
server = [[NSConnection rootProxyForConnectionWithRegisteredName: @"GSSpeechServer"
host: nil] retain];
if (nil == server)
{
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws launchApplication: @"GSSpeechServer"
showIcon: NO
autolaunch: NO];
}
NSSpeechSynthesizerClass = [NSSpeechSynthesizer class];
server = [[NSConnection rootProxyForConnectionWithRegisteredName: @"GSSpeechServer"
host: nil] retain];
if (nil == server)
{
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws launchApplication: @"GSSpeechServer"
showIcon: NO
autolaunch: NO];
}
}
+ (BOOL)isAnyApplicationSpeaking
{
return [server isSpeaking];
return [server isSpeaking];
}
// Never really allocate one of these.
+ (id)allocWithZone: (NSZone*)aZone
{
if (self == NSSpeechSynthesizerClass)
{
if (nil == server && !serverLaunchTested)
{
unsigned int i=0;
// Wait for up to five seconds for the server to launch, then give up.
for (i=0 ; i<50 ; i++)
{
server =
[[NSConnection rootProxyForConnectionWithRegisteredName:
@"GSSpeechServer"
host: nil]
retain];
if (nil != server)
{
break;
}
[NSThread sleepForTimeInterval: 0.1];
}
// Set a flag so we don't bother waiting for the speech server to
// launch the next time if it didn't work this time.
serverLaunchTested = YES;
}
// If there is no server, this will return nil
return [server newSynthesizer];
}
return [super allocWithZone: aZone];
if (self == NSSpeechSynthesizerClass)
{
if (nil == server && !serverLaunchTested)
{
unsigned int i = 0;
// Wait for up to five seconds for the server to launch, then give up.
for (i=0 ; i < 50 ; i++)
{
server = [NSConnection rootProxyForConnectionWithRegisteredName: @"GSSpeechServer"
host: nil];
RETAIN(server);
if (nil != server)
{
break;
}
[NSThread sleepForTimeInterval: 0.1];
}
// Set a flag so we don't bother waiting for the speech server to
// launch the next time if it didn't work this time.
serverLaunchTested = YES;
}
// If there is no server, this will return nil
return [server newSynthesizer];
}
return [super allocWithZone: aZone];
}
// configuring speech synthesis

View file

@ -1106,6 +1106,10 @@ many times.
selector: @selector(colorListChanged:)
name: NSColorListDidChangeNotification
object: nil];
[nc addObserver: self
selector: @selector(applicationDidChangeScreenParameters:)
name: NSApplicationDidChangeScreenParametersNotification
object: NSApp];
NSDebugLLog(@"NSWindow", @"NSWindow end of init\n");
return self;
@ -2083,16 +2087,12 @@ titleWithRepresentedFilename(NSString *representedFilename)
- (void) center
{
NSScreen *screen = [self screen];
NSSize screenSize;
NSPoint origin = _frame.origin;
if (screen == nil) {
screen = [NSScreen mainScreen];
}
screenSize = [screen visibleFrame].size;
origin.x = (screenSize.width - _frame.size.width) / 2;
origin.y = (screenSize.height - _frame.size.height) / 2;
NSRect screenFrame = [[NSScreen mainScreen] visibleFrame];
NSSize screenSize = screenFrame.size;
NSPoint origin = screenFrame.origin;
origin.x += (screenSize.width - _frame.size.width) / 2;
origin.y += (screenSize.height - _frame.size.height) / 2;
[self setFrameOrigin: origin];
}
@ -2227,6 +2227,20 @@ titleWithRepresentedFilename(NSString *representedFilename)
[self setFrame: r display: YES];
}
- (void) _applyFrame: (NSRect )frameRect
{
if (_windowNum)
{
[GSServerForWindow(self) placewindow: frameRect : _windowNum];
}
else
{
_frame = frameRect;
frameRect.origin = NSZeroPoint;
[_wv setFrame: frameRect];
}
}
- (void) setFrame: (NSRect)frameRect display: (BOOL)flag
{
if (_maximumSize.width > 0 && frameRect.size.width > _maximumSize.width)
@ -2245,12 +2259,13 @@ titleWithRepresentedFilename(NSString *representedFilename)
{
frameRect.size.height = _minimumSize.height;
}
/* Windows need to be constrained when displayed or resized - but only
titled windows are constrained */
if (_styleMask & NSTitledWindowMask)
{
frameRect = [self constrainFrameRect: frameRect toScreen: [self screen]];
frameRect = [self constrainFrameRect: frameRect
toScreen: [self _screenForFrame: frameRect]];
}
// If nothing changes, don't send it to the backend and don't redisplay
@ -2264,14 +2279,7 @@ titleWithRepresentedFilename(NSString *representedFilename)
* Now we can tell the graphics context to do the actual resizing.
* We will recieve an event to tell us when the resize is done.
*/
if (_windowNum)
[GSServerForWindow(self) placewindow: frameRect : _windowNum];
else
{
_frame = frameRect;
frameRect.origin = NSZeroPoint;
[_wv setFrame: frameRect];
}
[self _applyFrame: frameRect];
if (flag)
[self display];
@ -2494,7 +2502,7 @@ titleWithRepresentedFilename(NSString *representedFilename)
}
- (void) update
{
{
[nc postNotificationName: NSWindowDidUpdateNotification object: self];
}
@ -2701,6 +2709,54 @@ titleWithRepresentedFilename(NSString *representedFilename)
return _screen;
}
- (void) applicationDidChangeScreenParameters: (NSNotification *)aNotif
{
NSRect oldScreenFrame = [_screen frame];
int screenNumber = [_screen screenNumber];
NSRect newScreenFrame;
NSRect newFrame;
NSEnumerator *e;
NSScreen *scr;
// We need to get new screen from renewed screen list because
// [NSScreen mainScreen] returns NSScreen object of key window and that object
// will never be released.
e = [[NSScreen screens] objectEnumerator];
while ((scr = [e nextObject]))
{
if ([scr screenNumber] == screenNumber)
{
ASSIGN(_screen, scr);
break;
}
}
// Do not adjust frame for mini and appicon windows - it's a WM's job.
if ([self isKindOfClass: [NSMiniWindow class]] || self == [NSApp iconWindow])
return;
newScreenFrame = [_screen frame];
newFrame = _frame;
// Screen Y origin change.
newFrame.origin.y += newScreenFrame.origin.y - oldScreenFrame.origin.y;
// Screen height change.
newFrame.origin.y += newScreenFrame.size.height - oldScreenFrame.size.height;
// Screen X origin change. Screen width change shouldn't affect our frame.
newFrame.origin.x += newScreenFrame.origin.x - oldScreenFrame.origin.x;
/* Call backend's `placewindow::` directly because our origin in OpenStep
coordinates might be unchanged and `setFrame:display:` has check
for it. */
[self _applyFrame: newFrame];
[self display];
if (_autosaveName != nil)
{
[self saveFrameUsingName: _autosaveName];
}
}
- (void) setDepthLimit: (NSWindowDepth)limit
{
if (limit == 0)
@ -4127,16 +4183,25 @@ checkCursorRectanglesExited(NSView *theView, NSEvent *theEvent, NSPoint lastPoi
switch (sub)
{
case GSAppKitWindowMoved:
_frame.origin.x = (CGFloat)[theEvent data1];
_frame.origin.y = (CGFloat)[theEvent data2];
NSDebugLLog(@"Moving", @"Move event: %d %@",
(int)_windowNum, NSStringFromPoint(_frame.origin));
if (_autosaveName != nil)
{
[self saveFrameUsingName: _autosaveName];
}
[nc postNotificationName: NSWindowDidMoveNotification
object: self];
{
NSScreen *oldScreen = _screen;
_frame.origin.x = (CGFloat)[theEvent data1];
_frame.origin.y = (CGFloat)[theEvent data2];
NSDebugLLog(@"Moving", @"Move event: %d %@",
(int)_windowNum, NSStringFromPoint(_frame.origin));
if (_autosaveName != nil)
{
[self saveFrameUsingName: _autosaveName];
}
[nc postNotificationName: NSWindowDidMoveNotification
object: self];
if ([self screen] != oldScreen)
{
[nc postNotificationName: NSWindowDidChangeScreenNotification
object: self];
}
}
break;
case GSAppKitWindowResized:
@ -4918,16 +4983,6 @@ current key view.<br />
* the window could be placed (ie a rectangle excluding the dock).
*/
screen = [self _screenForFrame: fRect];
// Check whether a portion is showing somewhere...
if (screen == nil)
{
// If the window doesn't show up on any screen then we need
// to move it so it can be seen and assign it to the main
// screen...
screen = [NSScreen mainScreen];
NSDebugLLog(@"NSWindow", @"%s: re-assigning to main screen\n", __PRETTY_FUNCTION__);
}
nRect = [screen visibleFrame];
/*
@ -4979,9 +5034,6 @@ current key view.<br />
}
}
// Make sure we are using the new screen we are applying to...
ASSIGN(_screen, screen);
/*
* Set frame.
*/

View file

@ -812,6 +812,10 @@ const NSAppearanceName NSAppearanceNameAccessibilityHighContrastVibrantDark =
@"NSAppearanceNameAccessibilityHighContrastVibrantDark";
const NSAppearanceName NSAppearanceNameLightContent = @"NSAppearanceNameLightContent";
// Speech recognition...
const NSString *GSSpeechRecognizerDidRecognizeWordNotification = @"GSSpeechRecognizerDidRecognizeWordNotification";
extern void __objc_gui_force_linking (void);
void

View file

@ -28,7 +28,7 @@ include ../config.make
include ../Version
SUBPROJECTS = $(BUILD_SPEECH) $(BUILD_SOUND)
SUBPROJECTS = $(BUILD_SPEECH) $(BUILD_SOUND) $(BUILD_SPEECH_RECOGNIZER)
TOOL_NAME = make_services set_show_service gopen gclose gcloseall
SERVICE_NAME = GSspell

View file

@ -8,114 +8,119 @@ cst_voice *register_cmu_us_kal16();
* for resource-constrained platforms.
*/
@interface FliteSpeechEngine : GSSpeechEngine {
/** The audio device used for sound output. */
cst_audiodev *ad;
/** The current voice. Only one supported at the moment. */
cst_voice *v;
/** Flag set to tell the playback thread to exit. */
volatile BOOL shouldEndSpeaking;
/** Flag indicating whether the engine is currently speaking. */
volatile BOOL isSpeaking;
/** The audio device used for sound output. */
cst_audiodev *ad;
/** The current voice. Only one supported at the moment. */
cst_voice *v;
/** Flag set to tell the playback thread to exit. */
volatile BOOL shouldEndSpeaking;
/** Flag indicating whether the engine is currently speaking. */
volatile BOOL isSpeaking;
}
@end
@implementation FliteSpeechEngine
+ (void)initialize
{
flite_init();
flite_init();
}
- (id)init
{
if (nil == (self = [super init])) { return nil; }
// Only one voice supported by flite unless others are compiled in.
v = register_cmu_us_kal16();
if (NULL == v)
{
[self release];
return nil;
}
// Each wave should be the same format.
cst_wave *w = flite_text_to_wave("test", v);
ad = audio_open(w->sample_rate, w->num_channels, CST_AUDIO_LINEAR16);
delete_wave(w);
if (NULL == ad)
{
[self release];
return nil;
}
return self;
if (nil == (self = [super init])) { return nil; }
// Only one voice supported by flite unless others are compiled in.
v = register_cmu_us_kal16();
if (NULL == v)
{
[self release];
return nil;
}
// Each wave should be the same format.
cst_wave *w = flite_text_to_wave("test", v);
ad = audio_open(w->sample_rate, w->num_channels, CST_AUDIO_LINEAR16);
delete_wave(w);
if (NULL == ad)
{
[self release];
return nil;
}
return self;
}
- (void)sayString: (NSArray*)args
{
id pool = [NSAutoreleasePool new];
NSString *aString = [args objectAtIndex: 0];
int i,n,r;
int num_shorts;
BOOL didFinish = YES;
cst_wave *w = flite_text_to_wave([aString UTF8String], v);
num_shorts = w->num_samples * w->num_channels;
for (i=0; i < num_shorts; i += r/2)
{
if (num_shorts > i+CST_AUDIOBUFFSIZE)
{
n = CST_AUDIOBUFFSIZE;
}
else
{
n = num_shorts-i;
}
r = audio_write(ad, &w->samples[i], n*2);
if (shouldEndSpeaking)
{
didFinish = NO;
break;
}
}
isSpeaking = NO;
NS_DURING
[[args objectAtIndex: 1] didFinishSpeaking: didFinish];
NS_HANDLER
NS_ENDHANDLER
[args release];
[pool release];
delete_wave(w);
id pool = [NSAutoreleasePool new];
NSString *aString = [args objectAtIndex: 0];
int i,n,r;
int num_shorts;
BOOL didFinish = YES;
cst_wave *w = flite_text_to_wave([aString UTF8String], v);
num_shorts = w->num_samples * w->num_channels;
for (i=0; i < num_shorts; i += r/2)
{
if (num_shorts > i+CST_AUDIOBUFFSIZE)
{
n = CST_AUDIOBUFFSIZE;
}
else
{
n = num_shorts-i;
}
r = audio_write(ad, &w->samples[i], n*2);
if (shouldEndSpeaking)
{
didFinish = NO;
break;
}
}
isSpeaking = NO;
NS_DURING
[[args objectAtIndex: 1] didFinishSpeaking: didFinish];
NS_HANDLER
NS_ENDHANDLER;
[args release];
[pool release];
delete_wave(w);
}
- (void)startSpeaking: (NSString*)aString notifyWhenDone: (id)aDelegate
{
[[[aDelegate delegate] connectionForProxy] enableMultipleThreads];
NSArray *arg = [[NSArray alloc] initWithObjects: aString, aDelegate, nil];
shouldEndSpeaking = NO;
isSpeaking = YES;
[NSThread detachNewThreadSelector: @selector(sayString:)
toTarget: self
withObject: arg];
[[[aDelegate delegate] connectionForProxy] enableMultipleThreads];
NSArray *arg = [[NSArray alloc] initWithObjects: aString, aDelegate, nil];
shouldEndSpeaking = NO;
isSpeaking = YES;
[NSThread detachNewThreadSelector: @selector(sayString:)
toTarget: self
withObject: arg];
}
- (BOOL)isSpeaking
{
return isSpeaking;
return isSpeaking;
}
- (void)stopSpeaking
{
shouldEndSpeaking = YES;
// Spin until the other thread has died.
while (isSpeaking) {}
shouldEndSpeaking = YES;
// Spin until the other thread has died.
while (isSpeaking) {}
}
- (void)dealloc
{
[self stopSpeaking];
audio_close(ad);
[super dealloc];
[self stopSpeaking];
audio_close(ad);
[super dealloc];
}
@end
@implementation GSSpeechEngine (Flite)
+ (GSSpeechEngine*)defaultSpeechEngine
{
return [[[FliteSpeechEngine alloc] init] autorelease];
return [[[FliteSpeechEngine alloc] init] autorelease];
}
@end

View file

@ -8,65 +8,80 @@ static GSSpeechServer *sharedInstance;
@implementation GSSpeechServer
+ (void)initialize
{
sharedInstance = [self new];
sharedInstance = [self new];
}
+ (void)start
{
NSConnection *connection = [NSConnection defaultConnection];
[connection setRootObject: sharedInstance];
if (NO == [connection registerName: @"GSSpeechServer"])
{
return;
}
[[NSRunLoop currentRunLoop] run];
NSConnection *connection = [NSConnection defaultConnection];
[connection setRootObject: sharedInstance];
if (NO == [connection registerName: @"GSSpeechServer"])
{
return;
}
[[NSRunLoop currentRunLoop] run];
}
+ (id)sharedServer
{
return sharedInstance;
return sharedInstance;
}
- (id)init
{
if (nil == (self = [super init])) { return nil; }
engine = [GSSpeechEngine defaultSpeechEngine];
if (nil == engine)
{
[self release];
return nil;
}
return self;
if (nil == (self = [super init]))
{
return nil;
}
engine = [GSSpeechEngine defaultSpeechEngine];
if (nil == engine)
{
[self release];
return nil;
}
return self;
}
- (id)newSynthesizer
{
return [[GSSpeechSynthesizer new] autorelease];
return [[GSSpeechSynthesizer new] autorelease];
}
- (BOOL)startSpeakingString: (NSString*)aString notifyWhenDone: (id)client
{
[engine stopSpeaking];
[engine startSpeaking: aString notifyWhenDone: client];
return YES;
[engine stopSpeaking];
[engine startSpeaking: aString notifyWhenDone: client];
return YES;
}
- (void)stopSpeaking
{
[engine stopSpeaking];
[engine stopSpeaking];
}
- (BOOL)isSpeaking
{
return [engine isSpeaking];
return [engine isSpeaking];
}
- (NSArray*)voices
{
return [engine voices];
return [engine voices];
}
- (oneway void)setVoice: (NSString*)aVoice
{
[engine setVoice: aVoice];
[engine setVoice: aVoice];
}
- (NSString*)voice
{
return [engine voice];
return [engine voice];
}
- (NSString*)defaultVoice
{
return [engine defaultVoice];
return [engine defaultVoice];
}
@end

View file

@ -0,0 +1,26 @@
include $(GNUSTEP_MAKEFILES)/common.make
include ../../config.make
VERSION = 0.1
# This is an app not a tool because, eventually, it will present the user
# interface for the GUI part of the speech engine.
APP_NAME = GSSpeechRecognitionServer
GSSpeechRecognitionServer_LANGUAGES = English
GSSpeechRecognitionServer_OBJC_FILES = \
GSSpeechRecognitionEngine.m \
GSSpeechRecognitionServer.m \
main.m
# Add includes and link dirs....
GSSpeechRecognitionServer_OBJC_FILES += $(RECOGNIZER_ENGINE_CLASS)
GSSpeechRecognitionServer_INCLUDE_DIRS += $(RECOGNIZER_BASE_CFLAGS) \
-I../../Headers \
-I../../Headers/Additions
GSSpeechRecognitionServer_LIB_DIRS += -L../../Source/$(GNUSTEP_OBJ_DIR) \
-L/usr/local/lib -lgnustep-gui \
$(RECOGNIZER_BASE_LIBS)
include $(GNUSTEP_MAKEFILES)/application.make

View file

@ -0,0 +1,49 @@
/* Interface of class GSSpeechRecognitionEngine
Copyright (C) 2019 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: Fri Dec 6 04:55:59 EST 2019
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import <Foundation/Foundation.h>
#import <AppKit/NSSpeechRecognizer.h>
/**
* GSSpeechRecognitionEngine is an abstract speech server. One concrete subclass should
* be implemented for each speech recognition engine. Currently, only one may be compiled
* into the speech recognition server at any given time. This limitation may be removed
* in future if pluggable speech engines are considered beneficial.
*/
@interface GSSpeechRecognitionEngine : NSObject
- (void) start;
- (void) stop;
@end
@interface NSObject (GSSpeechRecognitionEngineDelegate)
@end
@interface GSSpeechRecognitionEngine (Default)
/**
* Returns a new instance of the default speech engine.
*/
+ (GSSpeechRecognitionEngine*)defaultSpeechRecognitionEngine;
@end

View file

@ -0,0 +1,49 @@
/* Implementation of class GSSpeechRecognitionEngine
Copyright (C) 2019 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: Fri Dec 6 04:55:59 EST 2019
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSSpeechRecognitionEngine.h"
/**
* Dummy implementation of a speech engine. Doesn't do anything.
*/
@implementation GSSpeechRecognitionEngine
+ (GSSpeechRecognitionEngine*) defaultSpeechEngine
{
return AUTORELEASE([[self alloc] init]);
}
- (void) recognize
{
}
- (void) start
{
}
- (void) stop
{
}
@end

View file

@ -0,0 +1,53 @@
/* Interface of class GSSpeechRecognitionServer
Copyright (C) 2019 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: Fri Dec 6 04:55:59 EST 2019
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import <Foundation/Foundation.h>
#import <AppKit/NSSpeechRecognizer.h>
@class GSSpeechRecognitionEngine;
/**
* GSSpeechRecognitionServer handles all of the engine-agnostic operations. Currently,
* there aren't any, but when the on-screen text interface is added it should
* go in here.
*/
@interface GSSpeechRecognitionServer : NSObject
{
GSSpeechRecognitionEngine *_engine;
NSMutableArray *_blocking;
}
/**
* Returns a shared instance of the speech server.
*/
+ (id)sharedServer;
// Add or remove from blocking list...
- (void) addToBlockingRecognizers: (NSString *)s;
- (void) removeFromBlockingRecognizers: (NSString *)s;
- (BOOL) isBlocking: (NSString *)s;
// Connection...
- (void) addClient;
@end

View file

@ -0,0 +1,146 @@
/* Implementation of class GSSpeechRecognitionServer
Copyright (C) 2019 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: Fri Dec 6 04:55:59 EST 2019
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSSpeechRecognitionServer.h"
#import "GSSpeechRecognitionEngine.h"
#import <Foundation/Foundation.h>
static GSSpeechRecognitionServer *_sharedInstance;
static int _clients = 0;
@implementation GSSpeechRecognitionServer
/**
* Monitor connection...
*/
+ (void)connectionDied: (NSNotification*)aNotification
{
NSArray *objs = [[aNotification object] localObjects];
NSEnumerator *en = [objs objectEnumerator];
id o = nil;
if(_clients > 0)
{
_clients--;
}
if(_clients == 0)
{
NSDebugLog(@"Client count is zero, exiting");
exit(0);
}
NSDebugLog(@"NSSpeechRecognizer server connection count = %d after disconnection", _clients);
while((o = [en nextObject]) != nil)
{
if ([o isKindOfClass: self])
{
RELEASE(o);
}
}
}
+ (void)initialize
{
_sharedInstance = [[self alloc] init];
_clients = 0;
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(connectionDied:)
name: NSConnectionDidDieNotification
object: nil];
}
+ (void)start
{
NSConnection *connection = [NSConnection defaultConnection];
[connection setRootObject: _sharedInstance];
RETAIN(connection);
if (NO == [connection registerName: @"GSSpeechRecognitionServer"])
{
NSLog(@"Could not register name, make sure another server is not running.");
return;
}
[[NSRunLoop currentRunLoop] run];
}
+ (id)sharedServer
{
NSDebugLog(@"NSSpeechRecognizer server connection count = %d after connection", _clients);
return _sharedInstance;
}
- (void) addClient
{
_clients++;
}
- (id)init
{
if (nil == (self = [super init]))
{
return nil;
}
_engine = [GSSpeechRecognitionEngine defaultSpeechRecognitionEngine];
if (nil == _engine)
{
[self release];
return nil;
}
else
{
NSDebugLog(@"Got engine starting... %@", _engine);
[_engine start];
}
_blocking = [[NSMutableArray alloc] initWithCapacity: 10];
return self;
}
- (void) dealloc
{
[_engine stop];
RELEASE(_engine);
RELEASE(_blocking);
[super dealloc];
}
- (void) addToBlockingRecognizers: (NSString *)s
{
[_blocking addObject: s];
}
- (void) removeFromBlockingRecognizers: (NSString *)s
{
[_blocking removeObject: s];
}
- (BOOL) isBlocking: (NSString *)s
{
return [[_blocking lastObject] isEqualToString: s];
}
@end

View file

@ -0,0 +1,233 @@
/* Implementation of class PocketsphinxSpeechRecognitionEngine
Copyright (C) 2019 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: Fri Dec 6 04:55:59 EST 2019
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSSpeechRecognitionEngine.h"
#import <Foundation/NSDistributedNotificationCenter.h>
#include <sphinxbase/err.h>
#include <sphinxbase/ad.h>
#include <pocketsphinx/pocketsphinx.h>
/**
* Implementation of a speech engine using pocketsphinx. This should be the default
* for resource-constrained platforms.
*/
#define MODELDIR "/share/pocketsphinx/model"
static const arg_t cont_args_def[] = {
POCKETSPHINX_OPTIONS,
/* Argument file. */
{"-argfile",
ARG_STRING,
NULL,
"Argument file giving extra arguments."},
{"-adcdev",
ARG_STRING,
NULL,
"Name of audio device to use for input."},
{"-infile",
ARG_STRING,
NULL,
"Audio file to transcribe."},
{"-inmic",
ARG_BOOLEAN,
"yes",
"Transcribe audio from microphone."},
{"-time",
ARG_BOOLEAN,
"no",
"Print word times in file transcription."},
CMDLN_EMPTY_OPTION
};
@interface PocketsphinxSpeechRecognitionEngine : GSSpeechRecognitionEngine
{
ps_decoder_t *ps;
cmd_ln_t *config;
FILE *fh;
char const *uttid;
int16 buf[512];
int rv;
int32 score;
NSThread *_listeningThread;
id<NSSpeechRecognizerDelegate> _delegate;
}
@end
@implementation PocketsphinxSpeechRecognitionEngine
- (id)init
{
if ((self = [super init]) != nil)
{
char *arg[3];
arg[0] = "";
arg[1] = "-inmic";
arg[2] = "yes";
config = cmd_ln_parse_r(NULL, cont_args_def, 3, arg, TRUE);
// turn off pocketsphinx output
err_set_logfp(NULL);
err_set_debug_level(0);
ps_default_search_args(config);
ps = ps_init(config);
if (ps == NULL)
{
cmd_ln_free_r(config);
NSLog(@"Could not start server");
return nil;
}
_listeningThread = nil;
}
return self;
}
- (void) _recognizedWord: (NSString *)word
{
[[NSDistributedNotificationCenter defaultCenter]
postNotificationName: GSSpeechRecognizerDidRecognizeWordNotification
object: word
userInfo: nil];
}
/*
* NOTE: This code is derived from continuous.c under pocketsphinx
* which is MIT licensed
* Main utterance processing loop:
* while (YES) {
* start utterance and wait for speech to process
* decoding till end-of-utterance silence will be detected
* print utterance result;
* }
*/
- (void) recognize
{
ad_rec_t *ad;
int16 adbuf[2048];
BOOL utt_started, in_speech;
int32 k;
char const *hyp;
NSDebugLog(@"** Starting speech recognition loop");
if ((ad = ad_open_dev(cmd_ln_str_r(config, "-adcdev"),
(int) cmd_ln_float32_r(config,
"-samprate"))) == NULL)
{
NSLog(@"Failed to open audio device");
return;
}
if (ad_start_rec(ad) < 0)
{
NSLog(@"Failed to start recording");
return;
}
if (ps_start_utt(ps) < 0)
{
NSLog(@"Failed to start utterance");
return;
}
utt_started = NO;
NSDebugLog(@"Ready.... <%@, %d>", _listeningThread, [_listeningThread isCancelled]);
while([_listeningThread isCancelled] == NO && _listeningThread != nil)
{
if ((k = ad_read(ad, adbuf, 2048)) < 0)
{
NSLog(@"Failed to read audio");
break;
}
ps_process_raw(ps, adbuf, k, FALSE, FALSE);
in_speech = ps_get_in_speech(ps);
if (in_speech && !utt_started)
{
utt_started = YES;
NSDebugLog(@"Listening...");
}
if (!in_speech && utt_started)
{
/* speech -> silence transition, time to start new utterance */
ps_end_utt(ps);
hyp = ps_get_hyp(ps, NULL);
if (hyp != NULL)
{
NSString *recognizedString = [NSString stringWithCString: hyp
encoding: NSUTF8StringEncoding];
[self performSelectorOnMainThread: @selector(_recognizedWord:)
withObject: recognizedString
waitUntilDone: NO];
NSDebugLog(@"Word: %s", hyp);
}
if (ps_start_utt(ps) < 0)
{
NSLog(@"Failed to start utterance");
}
utt_started = NO;
NSDebugLog(@"Ready.... <%@, %d>", _listeningThread, [_listeningThread isCancelled]);
}
[NSThread sleepForTimeInterval: 0.01];
}
// Close everything...
ps_end_utt(ps);
ad_close(ad);
}
- (void) start
{
_listeningThread =
[[NSThread alloc] initWithTarget: self
selector: @selector(recognize)
object: nil];
[_listeningThread setName: @"Speech Recognition Loop"];
NSLog(@"Starting - Thread info for speech recognition server %@", _listeningThread);
[_listeningThread start];
}
- (void) stop
{
NSLog(@"Stop listening thread %@", _listeningThread);
[_listeningThread cancel];
RELEASE(_listeningThread);
_listeningThread = nil;
}
@end
@implementation GSSpeechRecognitionEngine (Pocketsphinx)
+ (GSSpeechRecognitionEngine*)defaultSpeechRecognitionEngine
{
return AUTORELEASE([[PocketsphinxSpeechRecognitionEngine alloc] init]);
}
@end

View file

@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
@interface GSSpeechRecognitionServer
+ (void)start;
@end
int main(void)
{
[NSAutoreleasePool new];
[GSSpeechRecognitionServer start];
return 0;
}

View file

@ -8,7 +8,11 @@ ADDITIONAL_DEPENDS = @LIBS@
# Build speech and sound.
BUILD_SPEECH=@BUILD_SPEECH@
BUILD_SPEECH_RECOGNIZER=@BUILD_SPEECH_RECOGNIZER@
BUILD_SOUND=@BUILD_SOUND@
RECOGNIZER_BASE_LIBS=@RECOGNIZER_BASE_LIBS@
RECOGNIZER_BASE_CFLAGS=@RECOGNIZER_BASE_CFLAGS@
RECOGNIZER_ENGINE_CLASS=@RECOGNIZER_ENGINE_CLASS@
# CUPS
GSCUPS_CFLAGS = @GSCUPS_CFLAGS@

86
configure vendored
View file

@ -635,6 +635,10 @@ GSCUPS_LIBS
GSCUPS_LDFLAGS
GSCUPS_CFLAGS
have_cups
RECOGNIZER_ENGINE_CLASS
RECOGNIZER_BASE_CFLAGS
RECOGNIZER_BASE_LIBS
BUILD_SPEECH_RECOGNIZER
BUILD_SPEECH
BUILD_SOUND
HAVE_ICU
@ -729,6 +733,7 @@ with_icu_library
enable_aspell
enable_sound
enable_speech
enable_speech_recognizer
enable_cups
'
ac_precious_vars='build_alias
@ -1384,6 +1389,7 @@ Optional Features:
--disable-aspell Disable aspell for spellchecker
--disable-sound Disable sound
--disable-speech Disable speech server
--disable-speech-recognizer Disable speech recognition server
--disable-cups Disable cups printing support
Optional Packages:
@ -5662,6 +5668,86 @@ fi
fi
#--------------------------------------------------------------------
# NSSpeechRecognizer
#--------------------------------------------------------------------
# Check whether --enable-speech-recognizer was given.
if test "${enable_speech_recognizer+set}" = set; then :
enableval=$enable_speech_recognizer;
else
enable_speech_recognizer=yes
fi
BUILD_SPEECH_RECOGNIZER=
# has pocketsphinx, for speech recognition.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ps_start_utt in -lpocketsphinx" >&5
$as_echo_n "checking for ps_start_utt in -lpocketsphinx... " >&6; }
if ${ac_cv_lib_pocketsphinx_ps_start_utt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpocketsphinx $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char ps_start_utt ();
int
main ()
{
return ps_start_utt ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_pocketsphinx_ps_start_utt=yes
else
ac_cv_lib_pocketsphinx_ps_start_utt=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pocketsphinx_ps_start_utt" >&5
$as_echo "$ac_cv_lib_pocketsphinx_ps_start_utt" >&6; }
if test "x$ac_cv_lib_pocketsphinx_ps_start_utt" = xyes; then :
have_speech_recognizer=yes
else
have_speech_recognizer=no
fi
for ac_header in pocketsphinx/pocketsphinx_export.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "pocketsphinx/pocketsphinx_export.h" "ac_cv_header_pocketsphinx_pocketsphinx_export_h" "$ac_includes_default"
if test "x$ac_cv_header_pocketsphinx_pocketsphinx_export_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_POCKETSPHINX_POCKETSPHINX_EXPORT_H 1
_ACEOF
have_pocketsphinx=yes
else
have_pocketsphinx=no
fi
done
if test $have_pocketsphinx = yes -a $have_speech_recognizer = yes -a $enable_speech_recognizer = yes; then
BUILD_SPEECH_RECOGNIZER="speech_recognizer"
RECOGNIZER_BASE_LIBS=`pkg-config --libs pocketsphinx sphinxbase`
RECOGNIZER_BASE_CFLAGS=`pkg-config --cflags pocketsphinx sphinxbase`
RECOGNIZER_ENGINE_CLASS=PocketsphinxSpeechRecognitionEngine.m
fi
#--------------------------------------------------------------------
# Find CUPS
#--------------------------------------------------------------------

View file

@ -538,6 +538,28 @@ if test $have_flite = yes -a $have_speech = yes -a $enable_speech = yes; then
fi
AC_SUBST(BUILD_SPEECH)
#--------------------------------------------------------------------
# NSSpeechRecognizer
#--------------------------------------------------------------------
AC_ARG_ENABLE(speech-recognizer,
[ --disable-speech-recognizer Disable speech recognition server],,
enable_speech_recognizer=yes)
BUILD_SPEECH_RECOGNIZER=
# has pocketsphinx, for speech recognition.
AC_CHECK_LIB(pocketsphinx, ps_start_utt, have_speech_recognizer=yes, have_speech_recognizer=no)
AC_CHECK_HEADERS(pocketsphinx/pocketsphinx_export.h, have_pocketsphinx=yes, have_pocketsphinx=no)
if test $have_pocketsphinx = yes -a $have_speech_recognizer = yes -a $enable_speech_recognizer = yes; then
BUILD_SPEECH_RECOGNIZER="speech_recognizer"
RECOGNIZER_BASE_LIBS=`pkg-config --libs pocketsphinx sphinxbase`
RECOGNIZER_BASE_CFLAGS=`pkg-config --cflags pocketsphinx sphinxbase`
RECOGNIZER_ENGINE_CLASS=PocketsphinxSpeechRecognitionEngine.m
fi
AC_SUBST(BUILD_SPEECH_RECOGNIZER)
AC_SUBST(RECOGNIZER_BASE_LIBS)
AC_SUBST(RECOGNIZER_BASE_CFLAGS)
AC_SUBST(RECOGNIZER_ENGINE_CLASS)
#--------------------------------------------------------------------
# Find CUPS
#--------------------------------------------------------------------

View file

@ -11,10 +11,12 @@ install_gnustep_make() {
cd tools-make
if [ -n "$RUNTIME_VERSION" ]
then
echo "RUNTIME_VERSION=$RUNTIME_VERSION" > GNUstep.conf
WITH_RUNTIME_ABI="--with-runtime-abi=${RUNTIME_VERSION}"
else
WITH_RUNTIME_ABI=""
fi
./configure --prefix=$DEP_ROOT --with-library-combo=$LIBRARY_COMBO --with-user-config-file=$PWD/GNUstep.conf
make install
./configure --prefix=$DEP_ROOT --with-library-combo=$LIBRARY_COMBO $WITH_RUNTIME_ABI
make install
echo Objective-C build flags: `$HOME/staging/bin/gnustep-config --objc-flags`
}