Skip to content

Commit 89aefe3

Browse files
authored
Merge pull request #2 from tim-elmer/cscore
Ringtones, documentation, cleanup
2 parents 4d973d5 + 52652a5 commit 89aefe3

32 files changed

+1531
-295
lines changed

LICENSE.md

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,8 @@ MIT License
22

33
Copyright (c) 2020 Timothy Elmer
44

5-
Permission is hereby granted, free of charge, to any person obtaining a copy
6-
of this software and associated documentation files (the "Software"), to deal
7-
in the Software without restriction, including without limitation the rights
8-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9-
copies of the Software, and to permit persons to whom the Software is
10-
furnished to do so, subject to the following conditions:
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
116

12-
The above copyright notice and this permission notice shall be included in all
13-
copies or substantial portions of the Software.
7+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
148

15-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21-
SOFTWARE.
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,41 @@
11
# VoIPainter
2-
32
## Description
3+
VoIPainter is a simple Windows utility designed to change the background on a user's Cisco VoIP phone, without requiring access to the CUCM administrative backend.
44

5-
VoIPainter is a simple Windows utility designed to change the background on a user's Cisco VoIP phone, without requiring access to the CUCM backend.
5+
## Requirements / Caveats
6+
- The phone must be _owned by_ the executing user in CUCM.
7+
- _Personalization must be enabled_ on the phone in CUCM.
8+
- _Web access must be enabled_ on the phone in CUCM (the commands are sent via HTTP).
9+
- The executing user must have _local administrative privileges_; VoIPainter will open a socket on TCP port 80, which requires administrative rights.
10+
- _caveat:_ Key Expansion Modules / Sidecars are currently not supported. They are listed in the specification, but it's not trivially obvious how to specify deployment of a KEM over the phone's wallpaper itself, if possible at all, and I don't have one to test with.
611

7-
## **Requirements**
12+
## Use
13+
> Note that you may apply a background image, a ringtone, or both simultaneously.
814
9-
- The phone must be owned by the executing user in CUCM.
10-
- Personalization must be enabled on the phone in CUCM.
11-
- The phone must have web access enabled in CUCM (the commands are sent to it via HTTP).
12-
- The executing user must have *at least* local administrative privileges; VoIPainter will open a socket on TCP port 80, which requires administrative rights.
15+
### Applying a Background Image
16+
> Note that uncluttered, lower contrast images work best.
17+
1. Click the "Browse Image" button to select an image.
18+
1. Enter [required settings](#required-settings)
19+
1. Click "Apply"
1320

14-
## Use
15-
1. Open VoIPainter.
16-
1. Use the "Browse For Image" button to navigate to and select the desired image. Keep in mind that uncluttered, lower contrast images work best.
17-
1. Find your phone's IP address.[^1] Enter the address in the "Phone IP" field.
18-
[^1]: This can typically be acquired from the phone's settings menu under "Phone Information", "Status", or similar. It should be in the form `0.0.0.0`.
19-
1. Enter your domain username (e.g. Timothy Elmer -> telmer) in the "Username" field.
20-
1. Enter your domain password in the "Password" field.
21-
1. Select your phone model from the "Phone Model" dropdown. If you are unsure, the model is typically labeled on the back/bottom of the phone.
22-
1. Click "Apply".
21+
### Applying a Ringtone
22+
> Note that the chosen media file will automatically be trimmed to the first 20 seconds (2 seconds on older phones). If you wish to use a specific part of a longer file, you can first cut it down using an audio editor such as [Audacity](https://www.audacityteam.org/).
23+
1. Click the "Browse Ringtone" button to select an audio file.
24+
1. Enter [required settings](#required-settings)
25+
1. Click "Apply"
26+
27+
### Required Settings
28+
| Setting | Explanation |
29+
| ---: | --- |
30+
| Phone IP | The IP address of your phone. This can typically be acquired from the phone's settings menu under "Phone Information", "Status", or similar. It should be in the form `0.0.0.0`. This can be acquired from the phone's settings menu under "Phone Information", "Status", or similar. |
31+
| Username | Your domain username |
32+
| Password | Your domain password |
33+
| Phone Model | The model of your phone. If you are unsure, the model is typically labeled on the back/bottom of the device. |
34+
35+
## Settings
36+
| Setting | Explanation |
37+
| ---: | --- |
38+
| Resize Mode | How under/oversized images will be treated: Stretch: The image will be stretched to fit the screen; **Crop (recommended)**: The largest dimension will be cropped on the center of the image to fit the screen; Center: The image will be scaled to fit, and centered on the screen.|
39+
| Target Contrast | The maximum contrast that images should have. **The default value of `0.6` is recommended.** |
40+
| Automatically Duck Contrast | If images with excessive contrast should have their contrast lowered.
41+
| Ringtone Fade Out | How long the ringtone will fade out at the end. To not fade out, set to `0`. Must be between `0` and `20` seconds. |

VoIPainter/ABOUT.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
VoIPainter developed by Timothy Elmer under the MIT License:
2+
3+
Copyright (c) 2020 Timothy Elmer
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6+
7+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10+
11+
For convenience, the licenses for associated works are linked below. They are also listed, in order of inclusion on this page, in the NOTICES.md file distributed with this Software.
12+
13+
VoIPainter uses code based on the work of Gareth Palmer; [how to request CGI execution on a Cisco VoIP phone](https://usecallmanager.nz/cgi-execute-xml.html), [specifications for Cisco VoIP phone background image requirements](https://usecallmanager.nz/image-list-xml.html), and [specifications for Cisco VoIP phone ringtone requirements](https://usecallmanager.nz/ring-list-xml.html). These works are unlicensed, but have been used for reference rather than reproduction.
14+
15+
VoIPainter uses the [ImageSharp](https://github.com/SixLabors/ImageSharp) library for image manipulation. ImageSharp licensed under the [Apache License 2.0](https://github.com/SixLabors/ImageSharp/blob/master/LICENSE).
16+
17+
VoIPainter uses the [NAudio](https://github.com/naudio/NAudio) library for audio manipulation. NAudio is licensed under the [MS-PL](https://github.com/naudio/NAudio/blob/master/license.txt).
18+
19+
VoIPainter uses the [Markdig](https://github.com/lunet-io/markdig) and [Neo.Markdig.Xaml](https://github.com/neolithos/NeoMarkdigXaml) libraries for Markdown rendering. These libraries are licensed under the [BSD 2-Clause](https://github.com/lunet-io/markdig/blob/master/license.txt) and [Apache-2.0](https://github.com/neolithos/NeoMarkdigXaml/blob/master/LICENSE.md) respectively.
20+
21+
VoIPainter is written in [.NET core](https://github.com/dotnet/core). .NET core is licensed under the [MIT license](https://github.com/dotnet/core/blob/master/LICENSE.TXT).

VoIPainter/App.xaml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Application x:Class="VoIPainter.App"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:view="clr-namespace:VoIPainter.View">
45
<Application.Resources>
56
<Thickness x:Key="StandardMargin"
67
Left="2.5"
@@ -16,9 +17,14 @@
1617
<Setter Property="Margin"
1718
Value="{StaticResource StandardMargin}"/>
1819
</Style>
19-
<Style TargetType="TextBox">
20+
<Style TargetType="TextBox"
21+
x:Key="TextBoxStyle">
2022
<Setter Property="Margin"
2123
Value="{StaticResource StandardMargin}"/>
24+
<Setter Property="TextWrapping"
25+
Value="NoWrap"/>
26+
<Setter Property="MaxLines"
27+
Value="1"/>
2228
</Style>
2329
<Style TargetType="PasswordBox">
2430
<Setter Property="Margin"
@@ -36,5 +42,19 @@
3642
<Setter Property="Margin"
3743
Value="{StaticResource StandardMargin}"/>
3844
</Style>
45+
46+
<Style x:Key="textBoxInvalidated"
47+
TargetType="TextBox"
48+
BasedOn="{StaticResource TextBoxStyle}">
49+
<Style.Triggers>
50+
<Trigger Property="Validation.HasError"
51+
Value="True">
52+
<Setter Property="ToolTip"
53+
Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
54+
</Trigger>
55+
</Style.Triggers>
56+
</Style>
57+
58+
<view:IsStringNotNullOrWhitespaceConverter x:Key="IsStringNotNullOrWhitespaceConverter"/>
3959
</Application.Resources>
4060
</Application>

VoIPainter/Control/ImageReformatController.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,26 @@ public class ImageReformatController : INotifyPropertyChanged
2121
private readonly LogController _logController;
2222
private Image _original;
2323

24+
2425
/// <summary>
2526
/// The path to the image
2627
/// </summary>
28+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "General exceptions caught for display to user")]
2729
public string Path
2830
{
2931
get => _path;
3032
set
3133
{
3234
_path = value;
33-
_original = Image.Load(Path);
35+
try
36+
{
37+
_original = Image.Load(Path);
38+
}
39+
catch (Exception e)
40+
{
41+
_logController.Log(new Entry(LogSeverity.Error, e.Message));
42+
return;
43+
}
3444
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Path)));
3545
Format();
3646
}

VoIPainter/Control/ImageServerController.cs

Lines changed: 0 additions & 124 deletions
This file was deleted.

VoIPainter/Control/LogController.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,51 @@
11
using System;
22
using System.Collections.ObjectModel;
33
using System.Globalization;
4+
using System.IO;
45
using VoIPainter.Model.Logging;
56

67
namespace VoIPainter.Control
78
{
89
/// <summary>
910
/// Handles logging
1011
/// </summary>
11-
public class LogController
12+
public class LogController : IDisposable
1213
{
14+
private readonly StreamWriter _logStreamWriter;
15+
16+
/// <summary>
17+
/// Entries in the log
18+
/// </summary>
1319
public ObservableCollection<Entry> LogEntries { get; private set; } = new ObservableCollection<Entry>();
1420

21+
public LogController()
22+
{
23+
_logStreamWriter = new StreamWriter(File.OpenWrite(".\\VoIPainter.log"));
24+
}
25+
26+
/// <summary>
27+
/// Log an entry
28+
/// </summary>
29+
/// <param name="entry">The entry</param>
1530
public void Log(Entry entry)
1631
{
1732
if (entry is null)
1833
throw new ArgumentNullException(nameof(entry));
1934

2035
System.Windows.Application.Current.Dispatcher.Invoke(() => LogEntries.Add(entry));
21-
System.IO.File.AppendAllText(".\\VoIPainter.log", string.Format(CultureInfo.InvariantCulture, $"{Strings.LogFormat}\r\n", entry.Time, entry.Severity, entry.Message));
36+
_logStreamWriter.WriteLine(string.Format(CultureInfo.InvariantCulture, $"{Strings.LogFormat}\r\n", entry.Time, entry.Severity, entry.Message));
37+
}
38+
39+
protected virtual void Dispose(bool disposeManaged)
40+
{
41+
if (disposeManaged)
42+
_logStreamWriter.Dispose();
43+
}
44+
45+
public void Dispose()
46+
{
47+
Dispose(true);
48+
GC.SuppressFinalize(this);
2249
}
2350
}
2451
}

VoIPainter/Control/MainController.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ public class MainController
1010
private static MainController _instance;
1111

1212
public SettingsController SettingsController { get; }
13-
1413
public LogController LogController { get; } = new LogController();
15-
public ImageServerController ImageServerController { get; }
14+
public ServerController ImageServerController { get; }
1615
public RequestController RequestController { get; }
1716
public UpdateCheckController UpdateCheckController { get; }
1817
public ImageReformatController ImageReformatController { get; }
18+
public RingtoneReformatController RingtoneReformatController { get; }
1919
public View.MainWindow MainWindow { get; }
2020

2121
public MainController()
@@ -24,12 +24,16 @@ public MainController()
2424
throw new InvalidOperationException();
2525
_instance = this;
2626

27+
#region Initialize
2728
SettingsController = new SettingsController(LogController);
2829
ImageReformatController = new ImageReformatController(this);
29-
ImageServerController = new ImageServerController(this);
30+
RingtoneReformatController = new RingtoneReformatController(this);
31+
ImageServerController = new ServerController(this);
3032
RequestController = new RequestController(this);
3133
UpdateCheckController = new UpdateCheckController(LogController);
3234
MainWindow = new View.MainWindow(this);
35+
#endregion Initialize
36+
3337
MainWindow.Show();
3438
}
3539
}

0 commit comments

Comments
 (0)